如果我有一个类型,比如
int
,我可以通过在其末尾添加一个问号来使其可为空。例如,以下代码可以编译:
int? x = null;
而下面的代码,删除了问号,却没有:
int x = null; //throws a build error
我的理解是我可以对任何类型执行此操作;只需在其末尾添加一个问号,我总是可以为其分配一个空值。
但是,由于某种原因,这不适用于通用函数。考虑以下几点:
T? ReturnNull<T>() => null;
它抛出编译器错误 CS0403:
CS0403: 无法将 null 转换为类型参数“T”,因为它可能是不可为 null 的值类型。考虑使用 default('T') 代替。
什么!?如果我将问号添加到任何类型(类或结构)的名称中,我可以为其分配一个空值,并且它可以正常工作!
有趣的是,如果我要求
T
是一个类或一个结构:
T? ReturnNull<T>() where T : class => null;
T? ReturnNull<T>() where T : struct => null;
效果很好。我虽然可以通过重载上述两个函数来解决这个问题(一个类型可能不能同时是类和结构,对吧?)。
不,我不能。我想错了。以下引发构建错误:
T? ReturnNull<T>() where T : class => null;
T? ReturnNull<T>() where T : struct => null;
CS0128: 在此范围内已定义名为“ReturnNull”的局部变量或函数
什么!?我可以通过改变参数来重载函数!为什么不能通过更改泛型参数的类型约束来重载函数?类和结构不重叠!永远!
我很困惑。我对我的 IDE 非常友善,没有嘲笑它或其他任何事情;那不是问题。为什么这不起作用?
?
请不要同时提出多个问题。
“如果我有一个类型,比如
int
,我可以通过在其末尾添加一个问号来使其可为空”。不,你不能! int
与 int?
不是同一类型。一个是整数,另一个是可为空的整数。仅仅因为 c# 现在支持可为 null 的整数,并不意味着不可为 null 的整数已经消失。您的原始代码无法编译,正是因为该语言仍然提供不可为空的类型。
“为什么我不能通过改变类型约束来重载..”因为它还没有实现。这些问题在这里都是题外话。这相当于问为什么猪不能飞:因为上帝/进化没有为它们提供翅膀。为什么在这种情况下是无法回答的。