新手概念 · 类型
C# 里 var 与显式类型
最常见的误解:var 不是动态类型。变量依然有唯一的类型,由编译器从等号右边挑出来——只是你没亲笔写下它。
var 到底做了什么
类型来自右边,在编译期决定。Visual Studio 里这个程序会打印类型——而且从此再也不变:
var price = 9.99; // double —— 因为 9.99 是 double 字面量
var count = 42; // int —— 因为 42 是 int 字面量
var name = "Ada"; // string
Console.WriteLine(price.GetType()); // System.Double
Console.WriteLine(count.GetType()); // System.Int32
Console.WriteLine(name.GetType()); // System.String
(.GetType() 反射不在浏览器引擎的教学子集里——下面的论断用能在引擎里跑的检查来验证。)
引擎严格的类型检查能在现场证明同一件事——var 变量的行为和它的推断类型一模一样:
var x = 9.99; // 从这一行起 x 就是 double
int y = x; // CS0266: 和你写的 'double x = 9.99;' 一模一样
如果 var 是动态的(像 JavaScript),这个赋值早就编译过了。它没有——因为 x 是货真价实的 double,只是被推断出来而已。
第一天就该知道的两个字面量陷阱
var a = 7 / 2.0; // double: 3.5
var b = 7 / 2; // int: 3 —— 整数除法,小数没了!
Console.WriteLine(a);
Console.WriteLine(b);
var 忠实地继承表达式产出的东西——包括整数除法的意外(完整故事:为什么 7 / 2 是 3)。
var 的高光时刻
当类型在同一行里已经一目了然时用 var——那它就是纯粹的降噪:
var names = new List<string>(); // 显然是 List<string>
var dog = new Dog("Rex", 3); // 显然是 Dog
var total = price * quantity; // 类型简单时也行
泛型容器是最能感受它的地方——对比:
Dictionary<string, List<int>> scores = new Dictionary<string, List<int>>(); // 写了两遍
var scores2 = new Dictionary<string, List<int>>(); // 只写一遍
var scores = new Dictionary>();
scores["Ada"] = new List { 90, 85 };
Console.WriteLine($"Ada has {scores["Ada"].Count} scores");
显式类型什么时候赢
当类型是读者无法从别处得知的信息时,写出来:
- 数值意图:
double average = total / count;表明你期待小数。var average = total / count;会在两个 int 相除时悄悄继承 int——披着伪装的 bug。 - API 返回值:
var user = GetUser(id);逼着读者悬停或跳转。User user = GetUser(id);自解释。 - 长得像的类型:钱用
decimal还是double——差别重要,而 var 把它藏了。
var label = "count: ";
int n = 5;
Console.WriteLine(label + n); // 没问题:string + int 拼接
var wrong = n = label; // 故意写的胡话:把 string 塞进 int 槽
var 必须遵守的规矩
- 必须有初始值——
var x;非法(x 是什么类型?)。 - 之后不能换类型——推断完就钉死,和任何声明一样。
- 它不是 JavaScript 的
var,也不是dynamic——C# 的dynamic是另一个(罕见)关键字,跳过编译期检查。
团队惯例,压缩成一张表
| 场景 | 用 | 为什么 |
|---|---|---|
同一行有 new | var | 类型已经在右边写过了 |
| 数值声明 | 显式 | int 还是 double 是承重信息 |
| 方法调用的结果 | 显式(或好名字) | 读者不该被迫去查 |
| LINQ / 复杂泛型 | var | 完整类型名比逻辑本身还长 |
大多数风格指南(包括微软自己的)落在同一句话:右边能让类型一目了然时用 var,否则写出来。两个老手吵起来,吵的几乎全是"什么算一目了然"。