我正在将一堆代码从 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"
我需要能够具有相同的功能,否则它会破坏很多代码。 我错过了什么?
由于T
可以是引用类型或值类型,因此返回null
将不满足T是否为值类型。您应该返回:
return default(T);
从链接默认关键字:
给定参数化类型 T 的变量 t,语句 t = null 仅在 T 是引用类型且 t = 0 仅适用于数值类型而不适用于结构时才有效。解决方案是使用默认关键字,该关键字将为引用类型返回 null,为数值类型返回零。对于结构,它将返回初始化为零或 null 的结构的每个成员,具体取决于它们是值类型还是引用类型。对于可为 null 的值类型,default 返回 System.Nullable,该值像任何结构一样初始化。
更新 (2021-09-27)
使用 C# 7.1 中的新语法,您可以返回:
return default;
在 C# 的情况下,您必须使用 default(T),如果您只返回 T 而不是 T?,它将返回 0 而不是 Nothing 或 Null。
现在,如果按照您的示例 VB.net,您说返回的任何内容都是正确的,但是您是否尝试检查该函数的返回值。
喜欢
Dim c = <<your class object>>.FindItem("test",Nothing); // you have to pass valid values.
如果您检查 C 的值,那么它是 0 而不是什么都没有。
现在来谈谈 MSIL 级别发生的事情。
编译时,VB.net 代码并检查其 MSIL。 你会发现 伊尼托布 ! T 和这是默认值 (T) 的指令。它会自动执行此操作。因此,如果您从 C# 调用 VB.net 库,那么它也可以工作。
您可以使用此方法
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>()