我想知道为什么会出现这种情况,因为它与我的预期相反。这与 C# 中如何解释通用可空类型有关。
public static int? MyFunction(){
return default;
}
public static T MyFunctionGeneric<T>() {
return default;
}
public static T? MyFunctionGenericNullable<T>(){
return default;
}
public static void main(string[] args){
Console.WriteLine(MyFunction());
Console.WriteLine(MyFunctionGeneric<int?>());
Console.WriteLine(MyFunctionGenericNullable<int>());
}
正如预期的那样,当我将返回类型定义为int?
默认返回值时null
。
当我定义一个返回自身类型的泛型时也是这样的,因为int?
传入了,所以默认返回值是null
。
然而,在第三种情况下,即使返回类型从技术上讲是int?
,默认返回值也是0
。我必须传入int?
作为我的类型参数才能获得null
响应。请注意,即使我明确声明return default(T?)
这有点出乎意料,有人可以解释一下吗?
这一切都非常令人困惑,因为正如文档所述:
继续阅读文档,您会看到问题的答案(以粗体显示):
如果我们想要不同的行为,我们需要使用通用约束。文档没有列出所有有用的约束,在你的情况下应该是
where T:struct
如果与as一起使用,则将使用
int?
as 返回类型进行编译int
T
并且您将会得到
null
与前两种情况类似的结果。在 C# 中,
T?
根据是T
值类型还是引用类型,是两种不同事物的简写。T?
对于值类型(例如int?
,double?
)当 T 是值类型时,
T?
是 的简写Nullable<T>
。T?
对于引用类型(可空引用类型)从 C# 8.0 开始,当是引用类型(例如 、)
T?
时,也用于可空引用类型。此功能允许您指示引用类型可以保留空值(无需实际装入包装器)。示例:T
string?
MyClass?
Nullable<T>
在此上下文中,
string?
表示可空引用类型字符串,该字符串可能包含空值。T?
引用类型的注释仅为编译时注释,提供可空性警告和检查。它不会影响运行时行为或引入Nullable<T>
包装器。那么通用的呢
T
?一切都与限制有关。
由于您的示例中没有约束
T
,因此编译器会default
根据T
实例化的内容进行不同的处理:如果
T
是引用类型,default
将会null
因为default
对于引用类型 是null
。如果
T
是值类型,default
将是该类型的默认值(例如,0
对于int
)。您可以约束您的
MyFunctionGenericNullable<T>
,以便这T
是一个具有通用约束的值类型:...您将看到最初可能预期的行为。(不返回
0
。)原因是将函数标记为返回
T?
只是意味着它可以返回 null。但此函数中的 类型T
仍然int
与类型参数中传递的类型相同,但int?
转换为完全不同的类型:Nullable<int>
。