Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 来自';的C类型推断(";var";)赋值';零合并算子_C#_Type Inference_Null Coalescing Operator_Null Coalescing - Fatal编程技术网

C# 来自';的C类型推断(";var";)赋值';零合并算子

C# 来自';的C类型推断(";var";)赋值';零合并算子,c#,type-inference,null-coalescing-operator,null-coalescing,C#,Type Inference,Null Coalescing Operator,Null Coalescing,我已经阅读了许多关于空合并?运算符的SO问题,但它们似乎都没有解决以下具体问题,即既不涉及空性(),运算符优先级(和),也不特别涉及隐式转换(,和)。我也读了(更多)并试图阅读,但遗憾的是,所有这些都没有用 这就来了。以下两行之间的唯一区别是,第二行使用var进行类型推断,而第一行使用显式类型Random,但是第二行给出了如图所示的错误,而第一行正好 Random x = new Random() ?? (x = new Random()); // ok var y =

我已经阅读了许多关于空合并
运算符的SO问题,但它们似乎都没有解决以下具体问题,即既不涉及空性(),运算符优先级(和),也不特别涉及隐式转换(,和)。我也读了(更多)并试图阅读,但遗憾的是,所有这些都没有用


这就来了。以下两行之间的唯一区别是,第二行使用
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
非常明确地相反)的全部要点是,根据定义这样的运行时考虑是不可接受的

换言之,即使我们采用保守但完全可以辩护的规则“绝不在任何赋值
=
操作符之外窥视”,因此我们从
??
的右侧得不到任何有用的信息,那么仅基于左侧,整体结果必须与
Random
。也就是说,结果必须是
Random
或更具体(派生)的类型;它再普通不过了。因此,根据定义,
Random
不应该是推断类型吗?对于
var
的编译时使用

据我所知,使用运行时考虑因素来破坏
var
,显然违背了它的目的。这不正是
dynamic
的目的吗?所以我想问题是:

  • 对我理解C#static(即编译时)类型哲学而言,null合并运算符是唯一和/或罕见的例外吗
  • 如果是的话,那么这种设计与这里似乎正在发生的事情(即,故意将非确定性引入静态类型推断系统,而它以前没有展示)之间的利益或权衡是什么?难道
    dynamic
    不能在不破坏静态类型纯度的情况下实现吗
  • 强类型不是通过向开发人员提供可操作的反馈来实现编译时设计严密性的一个要点吗?为什么
    var
    不能保持严格的保守主义政策——总是推断可以静态推断的最具体的类型——同时空合并操作符根据未来的信息做它想做的事情

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

var    y = new Random() ?? (y = new Random()); 
编译器无法在编译时确定
y
的类型,因此开始叫喊将在运行时确定
??
的左侧是否为null

更好的例子是:

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

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

something
IA
A
B
的类型应该是什么?

这不是运行时的考虑因素

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


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

“结果必须是随机的或更具体(派生)的类型;不能更一般。”你可以向后看,将
var
替换为
object
将非常有效。
var
不是运行时,而是编译时<代码>动态是运行时的<创建代码>动态主要是为了通过DLR与动态语言(如Python)交互。@KennethK。这正是我的观点。你有什么特别的评论吗?@BenVoigt非常感谢;我修复了你提到的地方的错误,还有一个额外的错误。这很尴尬,因为信息偏序应该是我的主要专业领域之一。@GlennSlayden:嗯?不,第1行是不可推断的。它之所以编译是因为根本没有推论。这里存在的是一个无用的额外赋值,它发生在它赋值给的变量初始化之前(如果计算)。初始化总是会覆盖指定的值。这是一个问题,为什么它不能确定,当它和第一个一样明显时。@Novatata阅读我的例子,你就会明白为什么。在发布的问题中,这很明显,但在我提供的示例中,这一点并不明显。@CodingYoshi:对于您的示例,运行时的
null
,我并不在意。
var something=new A()的错误??新B()
显示您的示例没有编译是出于不同的原因,这是因为现在、运行时或任何时候,
a
中可能存储的任何对象都不可能成为
B
。这被强烈排除,因为NET不允许多个继承