在与同事讨论了c# 3中var关键字的使用后,我想知道人们对通过var适当使用类型推断的看法是什么?

例如,我很懒地在有问题的情况下使用var,例如:-

foreach(var item in someList) { // ... } // Type of 'item' not clear.
var something = someObject.SomeProperty; // Type of 'something' not clear.
var something = someMethod(); // Type of 'something' not clear.

var更合法的用法如下:-

var l = new List<string>(); // Obvious what l will be.
var s = new SomeClass(); // Obvious what s will be.

有趣的是,LINQ似乎是一个灰色区域,例如:-

var results = from r in dataContext.SomeTable
              select r; // Not *entirely clear* what results will be here.

结果很明显,因为它将是一个实现IEnumerable的类型,但它并不完全明显,与var声明一个新对象的方式相同。

当涉及到对象的LINQ时,情况就更糟了,例如:-

var results = from item in someList
              where item != 3
              select item;

这并不比等价的foreach(var item in someList){//…}相当于。

这里有一个关于类型安全的真正问题——例如,如果我们将该查询的结果放在一个接受IEnumerable<int>和IEnumerable<double>的重载方法中,调用者可能会无意中传入错误的类型。

Var确实保持强类型,但问题是,在定义中不立即显示类型是否危险,当重载意味着当你无意中将错误的类型传递给方法时,编译器可能不会发出错误,这种情况会被放大。


当前回答

你不需要写出类型名,这不会降低性能,因为类型是在编译时解析的。

其他回答

在大多数情况下,只是输入它更简单——想象一下

var sb = new StringBuilder();

而不是:

StringBuilder sb = new StringBuilder();

有时它是必需的,例如:匿名类型,比如。

var stuff = new { Name = "Me", Age = 20 };

我个人喜欢使用它,尽管它会降低代码的可读性和可维护性。

局部变量可以被赋予一个推断的var“类型”,而不是一个显式的类型。关键字var指示编译器从初始化语句右边的表达式推断变量的类型。

// z被编译为int类型

var z = 100;

// s被编译为下面的字符串

var s = "Hello";

// a被编译为int[]

var a = new[] { 0, 1, 2 };

// expr被编译为IEnumerable //或者IQueryable

var expr =
    from c in customers
    where c.City == "London"
    select c;

// anon被编译为匿名类型

var anon = new { Name = "Terry", Age = 34 };

// list被编译为list

var list = new List<int>();

var can only be used when a local variable is declared and initialized in the same statement; the variable cannot be initialized to null, or to a method group or an anonymous function.

Var不能在类范围内的字段上使用。

使用var声明的变量不能在初始化表达式中使用。换句话说,这个表达式是合法的:int i = (i = 20);但是这个表达式会产生一个编译时错误:var I = (I = 20);

多个隐式类型变量不能在同一个语句中初始化。

如果一个名为var的类型在作用域中,那么var关键字将解析为该类型名称,并且不会被视为隐式类型局部变量声明的一部分。

好吧,这个问题会一直固执己见,但我会试着给出我的观点-尽管我认为我的观点是如此混乱,你可能不会从中得到什么。

首先——有匿名类型,为此你需要使用“var”关键字来分配一个匿名类型作为类的对象——这里没有太多的讨论,“var”是必要的。

然而,对于更简单的类型,如int型、长型、字符串型等等,我倾向于输入适当的类型。主要是因为它有点像“懒人的工具”,我在这里看不到太多的好处,很少的按键和它可能带来的困惑,这是不值得的。特别是浮点数的各种类型(浮点数、双精度数、十进制数)使我感到困惑,因为我对字面量中的后缀不坚定——我喜欢在源代码中看到类型。

话虽如此,如果类型更复杂和/或它显式地重复在赋值的右侧,我倾向于大量使用var。这可以是一个List<string>或etc,例如:

var list = new List<string>();

在这种情况下,我认为没有必要重复类型两次——特别是当您开始更改代码和类型更改时——泛型类型可能会变得越来越复杂,因此必须更改它们两次只是一种痛苦。当然,如果你希望针对IList<string>编码,那么你必须显式地命名类型。

简而言之,我做了以下事情:

当类型很短或不能脱离上下文读取时,显式地命名类型 在必要时使用var(废话) 当var(在我看来)不影响可读性时,使用它来偷懒

这是个人品味的问题。当您习惯了动态类型的语言后,所有关于变量类型的烦恼都消失了。也就是说,如果你开始喜欢他们(我不确定是不是每个人都可以,但我喜欢)。

c#的var非常酷,因为它看起来像动态类型,但实际上是静态类型——编译器会强制正确使用。

变量的类型并不是那么重要(这在前面已经说过了)。从上下文(它与其他变量和方法的交互)和它的名称来看,它应该相对清晰——不要期望customerList包含int…

我还在等着看我的老板对这件事的看法——我得到了一个全面的“允许”,可以在3.5中使用任何新的结构,但是我们将如何维护呢?

有时编译器也能比开发人员“更好”地推断出需要什么——至少开发人员不了解他所使用的api需要什么。

例如-当使用linq时:

示例1

Func<Person, bool> predicate = (i) => i.Id < 10;
IEnumerable<Person> result = table.Where(predicate);

示例2

var predicate = (Person i) => i.Id < 10;
var result = table.Where(predicate);

在上面的代码中-假设一个是使用Linq到Nhibernate或Linq到SQL,示例1将 返回Person对象的整个结果集,然后在客户端进行筛选。 然而,示例2将在服务器上执行查询(例如在Sql server上使用Sql),因为编译器足够聪明,可以计算出Where函数应该采用表达式>而不是Func。

示例1中的结果在返回IEnumerable时也不能在服务器上进一步查询,而在示例2中,编译器可以计算出结果是否应该是IQueryable而不是IEnumerable