Jon Skeet 在他的书中提到了对隐式类型的 7 个限制。我需要澄清最后两个:
A.您希望变量具有的类型是初始化表达式的编译时类型。
B.初始化表达式不涉及被声明的变量。
本书涵盖的材料与发布顺序相同(C# 2 在 C# 3 之前)。此时尚未引入 C# 4,因此我假设A不指dynamic
. 那么,什么时候编译时类型会不同于初始化表达式的执行时类型呢?
至于B,初始化表达式何时可以涉及被声明的变量?
关于B,Henk 给出了一个完美的答案(编辑:它现在已被删除),尽管我发现它int x = x = 1;
编译起来很奇怪。(我会认为x在初始化程序之后才被认为是声明的。哦,好吧。)他的回答是:
int x = x = 1; // Compiles
var y = y = 2; // Does not compile
关于A和您关于编译时间类型何时与执行时间类型不匹配的问题,这是一个它们会有所不同的示例:
var foo = fooFactory.GetFoo();
...并且 fooFactory 上的该方法实现为 ....
public FooBase GetFoo() {
return new FooSubtype();
}
在这里,foo的类型是 FooBase(可能是接口、抽象类或未密封的具体类),并且(不进行强制转换)只有它的特性可用。显然,FooSubtype 实现或继承自 FooBase。
在这里可以看出foo在运行时持有的类型,只是因为我展示了 GetFoo() 的实现,但编译器不会检查它。事实上,实现甚至可能不可用(可能在另一个程序集中)或者它可能会有所不同(可能是虚拟的)。为了确定 GetFoo() 的编译时类型,因此只有方法声明是相关的。
我对A的想法:
这并不是说编译时间与执行类型不同,因为即使执行类型与编译类型不同(就像在任何返回类型为抽象类型的方法中一样),您也不能在执行时声明变量无论如何都要显式键入。
但是您可能希望使用更抽象的静态类型声明变量,即使可以在编译时定义真正的动态类型。考虑例如:
ISomething a = new MyOwnSomething();
你为什么想做这个?如果您明确地MyNewSomething
实现ISomething
了,那么您将不得不进行强制转换才能像ISomething
在 var 上声明的 if 一样使用它。这里演员阵容仍然完成,但你看不到相当丑陋的:
var a = new MyOwnSomething();
((ISomething)a).Whatever();
一个更人为的例子是初始化代码可以稍后更改,但是您要确保从此时起您只a
用作一个ISomething
,并且永远不会看到MyOwnSomething
类型的详细信息,或者它可能正在实现的其他接口,以便初始化类型的更改不会破坏代码。