在他的书中,Jon Skeet提到了对隐式打字的7个限制。我需要澄清最后两点:
A. 您希望变量具有的类型是初始化表达式的编译时类型。
B。初始化表达式不涉及声明的变量。
本书涵盖的材料与发布的顺序相同(C#3之前的C#2)。此时尚未引入C#4,因此我假设 A 未引用dynamic
。那么,编译时类型何时与初始化表达式的执行时类型不同?
对于 B ,初始化表达式何时可以涉及声明的变量?
答案 0 :(得分:3)
关于 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()的编译时类型,因此确定 foo 的编译时类型,只有方法声明是相关的。
答案 1 :(得分:2)
我对 A 的想法:
并不是编译时与执行类型不同,因为即使执行类型与编译类型不同(就像在返回类型为抽象类型的任何方法中),也不能声明变量无论如何使用显式输入执行类型。
但您可能希望使用更抽象的静态类型声明变量,即使可以在编译时定义 real 动态类型。考虑例如:
ISomething a = new MyOwnSomething();
你为什么要这样做?如果你的MyNewSomething
明确地实现了ISomething
,那么如果在var上声明,你必须像使用ISomething
一样进行强制转换。演员阵容仍然在这里完成,但你看不出相当丑陋:
var a = new MyOwnSomething();
((ISomething)a).Whatever();
一个更人为的例子是初始化代码可以在以后更改,但是您希望确保从此时起只使用a
作为ISomething
,并且永远不会看到详细信息MyOwnSomething
类型或其可能实现的其他接口,以便初始化类型的更改不会破坏代码。