C# var 关键字
var 是3.5新出的一个定义变量的类型,可代替任何类型,编译器会根据上下文来判断你到底是想用什么类型
比如写出如下代码:
var name = "水杯";
var price = 19.9;
var buy = true;
编译器会自动识别出变量name、price、buy的类型,如下图所示:
使用控制台输出它们的类型
Console.WriteLine($"name的类型:{name.GetType()}\r\n" +
$"price的类型:{price.GetType()}\r\n" +
$"buy的类型:{buy.GetType()}\r\n");
控制台输出的结果如下图所示:
对于很多的局部变量,我们都可以用var来声明,这样可以让我们更关注变量的语义而不用分心去考虑其类型,因为编译器会给我们选择合适的类型,但是不能滥用这种方式,因为会导致难于阅读,甚至可能产生微妙的类型转换bug,那么什么时候该用什么时候不该用呢?
C#使用var关键字的建议
在很多情况下,局部变量的类型完全可以从初始化语句看出来,这时候为了简化代码,完全可以使用var
示例代码如下所示:
MyType mytype = new MyType();
可以替换为:
var mytype = new MyType();
如果用工厂方法的返回值来初始化某个变量,那么其类型通常也是显而易见的
var thing = AccountFactory.CreateAccount();
某些方法的名称没有清晰地指出返回值的类型,例如
var result = someObject.DoSomeWork(anotherParameter)
这时候只要修改变量的名称,就能令代码变得清晰:
var HighestSellingProduct = someObject.DoSomeWork(anotherParameter)
尽管方法名本身没有指出返回的类型,但是我们可以很容易的推测出该变量的类型应该是Product
但是在有些时候使用var会触发各种形式的转换,有些转化是宽化转换(widening conversion)这种转化是安全的,例如float到double,而有些转化是窄化转换(narrowing converion)这种转化会让精度下降,例如从long到int的转换就会产生这个问题。如果我们明确地写出数值变量所应具备的类型,那么就可以更好地加以控制,而且编译器也会给出相应的提醒。
var f = GetMagicNumber();
var r = 100 * f / 6;
r的类型受到f的类型的影响,如果f为double类型,那么r也为double类型
比较一下下列两段代码的区别:
public IEnumerable<string> FindCustomersStartingWith1(string start)
{
IEnumerable<string> q =
from c in Customers
select c.ContactName;
var q2 = q.Where(s => s.StartsWith(start));
return q2;
}
public IEnumerable<string> FindCustomersStartingWith1(string start)
{
var q =
from c in Customers
select c.ContactName;
var q2 = q.Where(s => s.StartsWith(start));
return q2;
}
上一段代码设定了q的类型为IEnumerable,这将引发一定的性能问题,因为
访问数据库中返回值实际上是IQueryable类型,由于IQueryable继承于IEnumerable,因此编译器不会报错,这样会导致第二条的查询语句不是IQueryable.Where而是IEnumerable.Where这将导致性能损耗。IQueryable.Where与IEnumerable.Where的区别可简单理解为IQueryable.Where是在服务端执行查询,而IEnumerable.Where是先全部下载到本地再执行查询。
这样时候使用var编译器给出的自动推导类型是IQueryable,比起设定的类型IEnumerable在性能上会有提升。
参考:《Effective C#》——Bill Wagner