Yve*_*lpe 6 c# nullable .net-core c#-8.0 .net-core-3.0
编辑: 在给我模式选项等之前,请参见下面有关C#8.0中Null立场的更新。
原始问题
我正尝试使用C#8.0 <Nullable>enable</Nullable>标志将基本库升级为“空启用” 。
当尝试使用抽象以及特定的泛型时,我遇到了一些问题。考虑以下代码片段,该代码片段采用Action并将其转换为Func<TResult>。这是pre-nullable-enable:
public static Func<TResult> ToFunc<TResult>(this Action action)
=> () => { action(); return default; }
;
Run Code Online (Sandbox Code Playgroud)
但是post-nullable-enable我似乎很挣扎,因为我不能使TResult可TResult?为null(或),因为机智将要求where TResult: classor 的约束where TResult: struct。我无法组合这两个约束来让编译器知道TResult可以是类或值类型。目前我感到烦恼的是-因为无论类还是结构都应该能够表达出来,所以它将是可空的(无论以前的.NET初始化设计如何)。
因此,post-nullable-enable我似乎只有一个选择,那就是代码复制,下面是示例:
public static Func<TResult?> ToFuncClass<TResult>(this Action action)
where TResult : class
=> () => { action(); return null; }
;
public static Func<TResult?> ToFuncStruct<TResult>(this Action action)
where TResult : struct
=> () => { action(); return null; }
;
Run Code Online (Sandbox Code Playgroud)
无论是重复代码,以及在命名方案随之而来打扰了我很多。我可能会误解正确的用法,或者我错过了规范的另一个功能,但是您将如何解决呢?
更新:实际上,我认为我宁愿坚持使用自己的“空处理”实现,也不愿使用C#8.0的可为空功能。作为“无效”对象或充实的“ Option / Maybe / None”解决方案似乎可以更好地进行交流。我唯一担心的是,它在推动语言向前发展,培训新编码人员以及将另一个第三方/非本机解决方案引入普遍存在的null问题上不是很有帮助。因为自己使用null进行处理的实现非常好,但是却以不同的方式提出在每个代码库中,都需要由社区维护,并且您有各种不同的口味。因此,如果该语言完全执行它,并且标准提高了,那么它将是很有帮助的,并且将带来巨大的好处。我希望这会-显然不是,而且我了解。但是我觉得这是一个错失的机会。
伊夫·伊夫
原因在 部分中的尝试可空引用类型中进行了解释The issue with T?。基本上,没有办法解决这个问题。
首先,T当我们使用T?? 它是可空的还是不可空的?
T 的自然定义?意思是“任何可为空的类型”。然而,这意味着 T 将意味着“任何不可为空的类型”,这不是真的!现在可以用可空值类型替换 T(例如 bool?)。
其次,每种情况下使用的类型是不同的—— astring?仍然是stringwhileint?是 a Nullable<int>。每种情况下生成的具体方法完全不同。在一种情况下,你会得到一个
Func<string> ToFuncClass<string>(this Action action)
Run Code Online (Sandbox Code Playgroud)
另一方面,你得到一个
Func<Nullable<int>> ToFuncStruct<int>(this Action)
Run Code Online (Sandbox Code Playgroud)
接下来,重要的是要注意可空引用类型与可空值类型不同。可空值类型映射到 .NET 中的具体类类型。那么int?实际上是可空的。但是对于字符串?,它实际上是相同的字符串,但带有编译器生成的属性对其进行注释。这样做是为了向后兼容。换句话说,字符串?是一种“假类型”,而int?不是。
文章的例子证明了这一点:
可为空值类型和可为空引用类型之间的这种区别出现在如下模式中:
void M<T>(T? t) where T: notnull
Run Code Online (Sandbox Code Playgroud)
这意味着该参数是 T 的可为空版本,并且 T 被约束为非空。
如果 T 是一个字符串,那么 M 的实际签名将是:
M<string>([NullableAttribute] T t)
Run Code Online (Sandbox Code Playgroud)
但如果 T 是一个整数,那么 M 就是
M<int>(Nullable<int> t)
Run Code Online (Sandbox Code Playgroud)
这两个签名是根本不同的,这种不同是不可调和的。
| 归档时间: |
|
| 查看次数: |
119 次 |
| 最近记录: |