我正在将一堆代码从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'必须是非可空值类型才能在泛型类型或方法
中将其用作参数'T''System.Nullable<T>'
我需要能够拥有相同的功能,否则会破坏很多代码。我错过了什么?
答案 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>()