为什么不能在c#中将null转换为类型参数T?

时间:2015-01-25 04:23:16

标签: c# vb.net vb.net-to-c#

我正在将一堆代码从VB转换为C#,而我正在遇到一个方法的问题。这个VB方法效果很好:

Public Function FindItem(ByVal p_propertyName As String, ByVal p_value As Object) As T

    Dim index As Int32

    index = FindIndex(p_propertyName, p_value)

    If index >= 0 Then
        Return Me(index)
    End If

    Return Nothing

End Function

它允许为T返回Nothing(null)。

C#等价物不起作用:

public T FindItem(string p_propertyName, object p_value)
{
  Int32 index = FindIndex(p_propertyName, p_value);

  if (index >= 0) {
    return this[index];
  }
  return null;
}

它不会使用此错误进行编译:

  

类型'T'必须是非可空值类型才能在泛型类型或方法'System.Nullable<T>'

中将其用作参数'T'

我需要能够拥有相同的功能,否则会破坏很多代码。我错过了什么?

3 个答案:

答案 0 :(得分:10)

由于T可以是引用类型或值类型,因此如果T是值类型,则返回null将不会满足。你应该回来:

return default(T);

从链接default keyword

  

给定参数化类型T的变量t,语句t = null仅在T是引用类型时有效,并且t = 0仅适用于数值类型但不适用于结构。解决方案是使用default关键字,它将为引用类型返回null,为数值类型返回零。对于结构体,它将返回初始化为struct或null的结构的每个成员,具体取决于它们是值还是引用类型。对于可空值类型,default返回一个System.Nullable,它像任何struct一样初始化。

答案 1 :(得分:1)

在C#的情况下你必须使用默认值(T),如果你只返回T而不是T,它将返回0而不是Nothing或Null。

现在根据您的示例,如果是VB.net,则表示您返回Nothing,这是正确的,但您是否尝试检查该函数的返回值。

喜欢

Dim c = <<your class object>>.FindItem("test",Nothing);  // you have to pass valid values.

如果你检查C的值那么它就是0而不是什么。

现在谈到MSIL级别的情况。

编译VB.net代码并检查其MSIL时。你会发现 initobj!T ,这是默认的指令(T)。它自动执行此操作。因此,如果您从C#调用VB.net库,那么它也可以工作。

答案 2 :(得分:0)

您可以使用此方法

public static IList<int> ToIntList(this object values)
        {
            //try to convert using modified ChangeType which handles nullables
            try
            {
                if (values == null) return new List<int>();

                var charValues = values.ToType<string>();
                return charValues.Split(',').Select(n => Convert.ToInt32(n)).ToList();
            }
            //if there is an exception then get the default value of parameterized type T
            catch (Exception)
            {
                return new List<int>();
            }
        }

internal static object ChangeType(object value, Type conversionType)
        {
            if (conversionType == null)
            {
                throw new ArgumentNullException("conversionType");
            } 

            if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition() == typeof (Nullable<>))
            {
                if (value == null)
                {
                    return null;
                } 
                var nullableConverter = new NullableConverter(conversionType);
                conversionType = nullableConverter.UnderlyingType;
            }
            return Convert.ChangeType(value, conversionType);
        }

像这样使用

userVar.ToType<int>()
userVar.ToType<string>()