做家教网站如何招生,超市网站模版,北京高端定制网站建设,乐拾seo文章目录 一、前言二、隐式类型的局部变量2.1 var和匿名类型2.2 批注 三、总结 一、前言
C#中有一个 var 类型#xff0c;不管什么类型的变量#xff0c;都可以用它接收#xff0c;实属懒人最爱了。
我没有了解过它的底层#xff0c;甚至没看过它的说明文档#xff0c;也… 文章目录 一、前言二、隐式类型的局部变量2.1 var和匿名类型2.2 批注 三、总结 一、前言
C#中有一个 var 类型不管什么类型的变量都可以用它接收实属懒人最爱了。
我没有了解过它的底层甚至没看过它的说明文档也不知道怎么就用上它了。凭我经验这种 “隐式也可能是动态” 类型 应该只是效率比较低其他不会有多少负面影响。所以在不关心效率的场合我也就一直用着。
不过使用时偶尔也会有一些困扰比如
var c;
...此时会报错 于是我就知道了使用var类型时你必须声明与初始化一体否则就会报错。
还有时我会用var来接收一些写起来很复杂类型比如集合嵌套类型时间一长自己也不知道此处的var到底是啥类型。
因此我想进一步学习一下var了解它的用法和注意项不管能否解决上述困扰都不亏毕竟它的使用频率不低。
二、隐式类型的局部变量
局部变量可在不给出显式类型的情况下声明。 var 关键字指示编译器从初始化语句右侧的表达式推断变量的类型。 推断的类型可能是内置类型、匿名类型、用户定义类型或.NET类库中定义的类型。有关如何使用 var 来初始化数组的详情请参阅 隐式类型数组Implicity Typed Arrays 章节。 注意 这边说了是指示编译器从表达式推断表明var的解析要么是开始编译前要么是边指示边编译即在正式编译时已确定反正肯定是在运行之前确定的。故var不是动态类型。 下面示例展示了用 var 来声明局部变量的多种方式
// i is compiled as an int
var i 5;// s is compiled as a string
var s Hello;// a is compiled as int[]
var a new[] { 0, 1, 2 };// expr is compiled as IEnumerableCustomer
// or perhaps IQueryableCustomer
var expr from c in customerswhere c.City Londonselect c;// anon is compiled as an anonymous type
var anon new { Name Terry, Age 34 };// list is compiled as Listint
var list new Listint();首先重要一点是理解 var 关键字并不意味着 “variant变体类型变形类似动态类型吧即类型会发生变化” 也不表示该变量是松散类型loosely type也叫弱类型的或后绑定的late-bound。它仅表示编译器会确定并分配最合适的类型。
var 关键字可在以下情况使用
局部变量变量声明在方法体中如上例所示。在 for 初始化语句中。for(var x 1; x 10; x)在 foreach 初始化语句中foreach(var item in list) {...}在 using 语句中using (var file new SteamReader(C:\\myfile.txt)) {...}显然用作方法体中局部变量的情况比较多。
2.1 var和匿名类型
许多情况下var 的使用是可选的只是为了语法上的便利。 然而当使用匿名类型初始化变量时若你之后要访问对象的属性则必须将该变量声明为 var 。这是 LINQ Query表达式中的常见场景。详细信息参阅 匿名类型 章节。
从源码角度看匿名类型没有名称匿名类就是将几个变量用花括号括起来类本身没有名称。 因此若查询变量已使用 var 初始化则访问返回的对象序列中属性的唯一方法是在 foreach 语句中使用 var 作为迭代变量的类型。var相当于变成访问匿名类型对象的入口
class ImplicitlyTypedLocals2
{static void Main(){string[] words { aPPLE, BLUeBeRrY, cHeRry };// 若一次查询产生了一个匿名类型的序列// 可在foreach语句只能使用var来访问属性var upperLowerWords from w in wordsselect new { Upper w.ToUpper(), Lower w.ToLower() };// 执行查询foreach(var ul in upperLowerWords){Console.WriteLine(Uppercase:{0}, Lowercase:{1}, ul.Upper, ul.Lower);}}
}
/*输出Uppercase:APPLE, Lowercase:appleUppercase:BLUEBERRY, Lowercase:blueberryUppercase:CHERRY, Lowercae:cherry
*/
2.2 批注
以下限制用于隐式类型变量声明中
var 只能在同一语句中声明和初始化局部变量时才能使用且变量不能为空、方法组或匿名函数。var 不能用于类中字段。使用 var 声明的变量不能用于初始化表达式中。 换句话说这个表达式是合法的int i (i 20); 而该表达式则会生成编译时错误compile-time errorvar i (i 20);多个隐式类型变量无法在同一语句中初始化。若作用域内有一个名为 var 的类型则 var 关键字将解析为该类型名称并且不会被视为隐式类型局部变量声明。class var {}void Method()
{var v;...
}使用 var 关键字的隐式类型只能应用于局部方法作用域local method scope内的变量。隐式类型不适用于类字段因为C#编译器在处理代码时会遇到逻辑悖论logical paradox编译器需要知道字段的类型但在分析赋值表达式之前无法确定类型且表达式在不知道类型的情况下无法进行评估。考虑下面代码
private var bookTitles;bookTitles 是一个 var 类型的类字段。因为该字段没有求值表达式因此编译器不可能推断出 bookTitles 是什么类型。此外向字段添加表达式就像局部变量一样也是不够的
private var bookTitles new Liststring();当编译器在代码编译期间遇到字段时它会在处理与之关联的任何表达式之前记录每个字段的类型即在字段解析时我会先确认字段类型再处理表达式而字段是var就不知道字段类型了。编译器在尝试解析 bookTitles 时遇到了同样的悖论它需要知道字段的类型但编译器通常会通过分析表达式来确定 var 类型如果事先不知道类型这是不可能的。 补充 这部分比较抽象因为和C#编译器本身的设计有关。 简单介绍一下C#编译器的工作流程 首先遍历每个源文件并进行顶层的解析。即在所有嵌套的层级上识别每个名称空间、类、结构、枚举、接口和委托类型声明。然后解析字段声明、方法声明等。实际上除了方法体的内容都会被解析解析完外面的之后会回来解析方法体。 如果有var字段那么在表达式被解析之前就无法确定字段的类型而这发生在我们知道字段的类型之后这就冲突了。 你也许会发现 var 对于难以确定查询变量的确切构造类型的查询表达式也很有用。这可能出现在分组和排序操作中。
当特定类型的变量在键盘上输入很繁琐或者完整输入类型无法增加代码可读性时var 关键字也很有用。var 以这种方式发挥作用的一个例子是嵌套泛型类型例如与分组操作一起使用。在以下查询中查询变量的类型为 IEnumerableIGroupingstring, Student 。只要你和其他维护代码的人都知道这点为了方便和简洁而使用隐式类型就没有问题。
// 和前面例子相同除了我们使用了整个last name作为关键字
// 查询变量是一个 IEnumerableIGroupingstring, Student
var studentQuery3 from student in studentsgroup student by student.Last;使用 var 有助于简化代码但其使用应仅限于需要它的情况下或者当它使你的代码更易于阅读时。 三、总结
总结一下 var 的内容其实不多主要就是
要了解它并不是动态类型它指示编译器根据表达式来推断类型。故它是编译时的代码不会影响运行效率。主要应用场景就是接收LINQ Query、访问匿名类变量的属性、接收一些比较难写的类型以增强代码可读性所以若你使用var但不知道它对应啥类型那很可能是你自己没理清。