来自'??'的C#类型推断(“var”)赋值null-coalescing operator

时间:2017-07-09 01:59:19

标签: c# type-inference null-coalescing-operator null-coalescing

我已经阅读了关于空合并??运算符的许多SO问题,但它们似乎都没有解决以下特定问题,它既不涉及可空性({{3} }),运算符优先级herehere),特别是隐式转换herehere,{ {3}}和here)。我还阅读了here(更多here)并尝试阅读.NET docs,但遗憾的是都无济于事。

所以这里。以下两行之间的唯一区别是在第二行中使用var进行类型推断,而在第一行中使用显式类型Random,而第二行则给出如图所示的错误,而第一行是很好。

Random x = new Random() ?? (x = new Random());        // ok

var    y = new Random() ?? (y = new Random());        // CS0841
                        //  ^-------- error here
  

CS0841:在声明

之前,不能使用局部变量'y'

使结果不确定的第二行究竟是什么?

从上面引用的hubub中,我了解到??运算符左侧null的可能性引入了对其权利的实际实例化类型的运行时确定的依赖性 - 侧。嗯,好吧,我想,......这意味着什么?通常这个网站上??运营商的警报声通常都是警告......

现在归零,我认为var关键字的整个点(非常明确地反对dynamic)是因为它不容易受到运行时考虑因素的影响, < em>按照定义

换句话说,即使我们采用保守但完全可辩护的“从不窥视任何任务=运算符”的规则,因此我们从{{的右侧 - 得不到任何有用的信息。 1}},然后仅基于左侧,整体结果 必须 与“??”兼容。也就是说,结果必须是Random或更具体(派生)的类型;它不能更一般。因此,对于Random的编译时使用,根据定义,Random不应该是推断类型?

据我所知,用运行时考虑因素破坏var会使其失败。这不正是var的意思吗?所以我想问题是:

  • null-coalescing 运算符是否是我理解C#静态(即编译时)键入哲学的唯一和/或罕见的例外?
  • 如果是,那么这个设计与这里似乎正在发生什么之间的好处或权衡是什么,即故意将非确定性引入静态类型推理系统,以及之前没有表现出来的?在不破坏静态类型的纯度的情况下,dynamic无法实现?
  • 通过对开发人员的可操作反馈,是不是强类型的主要要点之一,以实现编译时设计的严谨性?为什么dynamic不能保持严格保守主义的政策 - 始终推断可以静态推断的最具体的类型 - 同时因为null-coalescing运算符是根据未来的信息做任何想做的事情?

2 个答案:

答案 0 :(得分:4)

这不是运行时考虑因素。

使用var声明的变量的编译时类型是其初始值设定项的静态类型。 ??表达式的静态类型是两个操作数的静态类型的常见类型。但是第二个操作数的静态类型是y的静态类型,这是未知的。因此整个初始化程序的静态类型是未知的,并且演绎失败。

确实存在初始化一致的类型,但使用C#推理规则无法找到它们。

答案 1 :(得分:0)

使用var时,类型在编译时计算出来。因此,当你写这个:

var    y = new Random() ?? (y = new Random()); 

编译器在编译时无法确定y的类型是什么,因此开始大喊 - 判断??的左侧是否为空,将在运行时确定。

更好的例子是:

public interface IA { void Do(); }
public class A : IA { ... }
public class B : IA { ... }

A a = null;
var something = a ?? new B(); 

something的类型应该是什么:IAAB