简体   繁体   English

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

[英]C# type inference (“var”) assignment from '??' null-coalescing operator

I've read many of the SO questions on the null coalescing ?? 我已经阅读了关于空合并的许多SO问题?? operator but none of them seem to address the following specific issue, which concerns neither nullability ( here ), operator precedence ( here and here ) nor especially implicit conversion ( here , here , here and here ). 运算符但它们似乎都没有解决以下特定问题,它既不涉及可空性此处 ), 运算符优先级此处此处 ),也不涉及隐式转换此处此处此处此处 )。 I've also read the .NET docs (more here ) and tried to read the offical spec , but sadly all to no avail. 我也阅读了.NET文档 (更多这里 )并尝试阅读官方规范 ,但遗憾的是都无济于事。


So here goes. 所以这里。 The only difference between the following two lines is the use of var for type inference in the second, versus explicit type Random in the first, yet the second line gives the error as shown, whereas the first is just fine. 以下两行之间的唯一区别是在第二行中使用var作为类型推断,而在第一行中使用显式类型Random ,而第二行则给出如图所示的错误,而第一行则很好。

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

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

CS0841: Cannot use local variable 'y' before it is declared CS0841:在声明之前不能使用局部变量'y'

What is it precisely about the second line that makes the outcome uncertain? 第二条线是什么让结果不确定?

From the hubub I cited above, I learned that the possibility of the left-side of the ?? 从我上面提到的hubub,我了解到左侧的可能性?? operator being null introduces a dependency on the runtime determination of the actual instantiated type of its right-side. operator为null引入了对其右侧的实际实例化类型的运行时确定的依赖性。 Hmm, ok, I guess,... whatever that means? 嗯,好吧,我想,......这意味着什么? Maybe the amount of alarm generally wafting about the ?? 也许警报的数量一般都在飘荡?? operator on this site should have been some kind of dire warning... 这个网站上的运营商应该是某种可怕的警告......

Zeroing-in now, I thought that the whole point of the var keyword (as very specifically opposed to dynamic ) was that it was not suscceptible to runtime considerations like that, by definition . 现在归零,我认为var关键字的整个要点(与dynamic非常特别相反)是, 根据定义 ,它不像运行时那样容易受到影响

In other words, even if we adopt the conservative but perfectly defensible rule of "never peering beyond any assignment = operator", such that we therefore get no helpful information whatsoever from the right-side of the ?? 换句话说,即使我们采取“永不窥视超越任何分配保守的,但完全站得住脚规则=运算符”,这样,我们因此与的右侧任何没有得到有用的信息?? , then based on the left-side alone, the overall result must be "compatible with" Random . ,然后单独基于左侧,整体结果必须 “兼容” Random That is, the result must be Random or a more specific (derived) type; 也就是说,结果必须是Random或更具体的(派生的)类型; it cannot be more general. 它不能更一般。 By definition, therefore, shouldn't Random be the inferred type, for this compile-time use of var ? 因此,根据定义,不应该将Random作为推断类型,因为这个编译时使用var

As far as I can understand, corrupting var with runtime considerations summarily defeats its purpose. 据我所知,用运行时考虑因素破坏var使其失败。 Isn't that precisely what dynamic is for? 这不正是dynamic的意义吗? So I guess the questions are: 所以我猜问题是:

  • Is the null-coalescing operator a lone and/or rare exception to my understanding of C# static (ie, compile-time) typing philosophy? 对于我对C#静态(即编译时)打字哲学的理解, null-coalescing运算符是一个单独的和/或罕见的例外吗?
  • If yes, then what are the benefits or tradeoffs between this design vs. what seems to be going on here, namely, deliberately introducing non-determinism to a system of static type inference, and which it did not previously exhibit? 如果是,那么这个设计与这里似乎正在发生的事情之间的好处或权衡是什么,即故意将非确定性引入静态类型推理系统,以及之前没有表现出来的? Couldn't dynamic have been implemented without corrupting the purity of static typing? 如果不破坏静态类型的纯度, dynamic是否已经实现?
  • Isn't one of the main points of strong-typing to enable compile-time design rigor via actionable feedback to the developer? 通过对开发人员的可操作反馈来实现编译时设计的严谨性不是强类型的要点之一吗? Why can't var just maintain a policy of strict conservatism-- always inferring the most-specific type that can be statically inferred--at the same time as the null-coalescing operator is doing whatever it wants to do based on information from the future? 为什么var不能保持严格保守主义的策略 - 总是推断出可以静态推断的最具体的类型 - 同时空归合运算符根据来自的信息做任何想做的事情。未来?

It's not a runtime consideration. 这不是运行时考虑因素。

The compile time type of a variable declared using var is the static type of its initializer. 使用var声明的变量的编译时类型是其初始化程序的静态类型。 The static type of a ?? 静态类型?? expression is the common type of the static type of both operands. expression是两个操作数的静态类型的常见类型。 But the static type of the second operand is the static type of y , which isn't known. 但是第二个操作数的静态类型是y的静态类型,这是未知的。 Therefore the static type of the whole initializer is unknown, and deduction fails. 因此,整个初始化程序的静态类型是未知的,并且扣除失败。

It's true that there exist types for which the initialization would be consistent, but they can't be found using the C# inference rules. 确实存在初始化一致的类型,但是使用C#推理规则无法找到它们。

When you use var , the type is figured out at compile time. 使用var ,类型在编译时计算出来。 Therefore, when you write this: 因此,当你写这个:

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

the compiler cannot determine what y 's type is at compile time and thus starts yelling-the decision whether the left side of ?? 编译器无法确定编译时y的类型是什么,因此开始大喊大叫 - 决定是否左侧?? is null or not, will be determined at runtime. 是否为null,将在运行时确定。

A better example would be: 一个更好的例子是:

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

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

What should be the type of something : IA , A or B ? 应该是什么类型的somethingIAA还是B

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM