C# 中的隐式类型的局部变量是为了支持匿名类型而出现的,并且也是为了解决一部分查询操作返回的结果是 IQueryable 类型,而另一部分查询返回的结果是 IEnumerable 类型导致的把 IQueryable 当作 IEnumerable 来使用,进而无法使用 IQueryProvider 提供的增强功能。在这里一定会有读者担心如果没有把变量的类型写明是不是会造成类型安全问题。那么,在这里我要告诉各位读者的是开发人员有没有写明变量类型与变量的类型安全毫无关系,所以大家不必担心。在大部分情况下使用 var 声明隐式类型的变量,编译器会自动选择合适的类型来处理。看到这里,一定会有读者说既然有明确的类型,为什么不指定明确的类型呢,而且使用隐式变量也会容易让其他开发人员搞不清楚变量的类型。那么我现在就给大家解答一下。
首先,使用明确的类型有可能会造成代码的执行顺序改变,这一点我将在后面的文章中具体讲解。其次,这就是一个编码命名习惯问题了,我们在 new 一个对象时可以通过等号右边的类型得知变量的类型。例如:
var s = new Student();
从上面的代码中我们可以看出变量 s 的类型是 Student ,但是这段代码还有一个问题,就是变量的命名。s 这个名字混在大量的代码中很难一眼看出它的类型。这时我们将变量名改为 student 就很容易看出变量类型了。这个变量命名规则一定要记住,这条规则可以说是你牢记于心的。这种错误并不只是开发新手会犯的,我在实际工作和项目中就见过一些所谓的技术大牛出现这种错误,最后自己都不知道自己命名的这变量是干嘛的,是什么类型。 [笑哭] 一些有经验的开发人员往往会对新手开发人员说不要使用匿名类型,因为它会影响性能影响静态类型检查。那么,我在这里要说的是这完全都是在胡扯!首先局部变量类型推断不等于动态类型检查,var 声明的变量不是动态变量,c# 会根据赋值符号等号右边的值的类型来确定等号左边的变量类型。其次,编译器会自动判断类型。这里我需要强调的是隐式类型变量的真实类型是由方法的签名决定的,也就是说不管这个隐式类型的真实类型是从某个类继承的类还是实现了一个或多个接口的类,只要没有明确执行类型转换,编译器都会根据方法的签名来决定隐式类型的真实类型。
上面我们说了隐式类型的优点,那么我们再来说一下隐式类型的缺点。首先 var 声明的变量会让代码阅读起来有些困难,因为有可能我们所认为的类型和编译器最终的类型不一样,进而导致在代码中错误的维护开发导致 bug 。这是因为 var 声明的变量编译器会自动推断其类型,但是开发人员看不到推断出来的类型。其次,如果使用隐式类型的变量的真实类型是内置的数值类型的话会产生类型转换精度下降的问题。这个问题只会发生在窄转换中,例如 long 向 int 转换。这个问题并不是编译器问题,而是因为编译器会自己设定变量的类型,也就是说根据赋值符号等号右侧的部分做出的最佳选择。
Tip: 这里指的隐式类型变量是指局部变量