在与同事讨论了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确实保持强类型,但问题是,在定义中不立即显示类型是否危险,当重载意味着当你无意中将错误的类型传递给方法时,编译器可能不会发出错误,这种情况会被放大。


当前回答

@Keith -

在你们的比较中 IEnumerable < int > IEnumerable<double>你不需要 担心——如果你传递了错误的类型 您的代码无论如何都无法编译。

这并不完全正确——如果一个方法同时重载到IEnumerable<int>和IEnumerable<double>,那么它可能会无声地将意外推断的类型(由于程序中的其他一些更改)传递给错误的重载,从而导致不正确的行为。

我想问题是这种情况出现的可能性有多大!

我猜部分问题是var给给定的声明增加了多少混乱——如果不清楚某个东西是什么类型(尽管它是强类型的,编译器完全理解它是什么类型),有人可能会掩盖一个类型安全错误,或者至少需要更长的时间来理解一段代码。

其他回答

静态类型是关于契约的,而不是源代码。这里的想法是需要将静态信息放在“应该”是一个小方法的单行上。一般指南建议每个方法不要超过25行。

如果一个方法足够大,以至于您无法跟踪该方法中的单个变量,那么您做错了其他事情,这将使任何对var的批评相形见绌。

实际上,var的一个重要论点是它可以使重构更简单,因为你不再需要担心你的声明过于严格(例如,当你应该使用IList<>或IEnumerable<>时,你使用了List<>)。您仍然需要考虑新的方法签名,但至少不必返回并更改声明来匹配。

在IEnumerable<int>和IEnumerable<double>之间的比较中,你不需要担心-如果你传递了错误的类型,你的代码无论如何都不会编译。

不需要考虑类型安全,因为var不是动态的。这只是编译器的魔法,任何类型不安全的调用都会被捕获。

Linq绝对需要Var:

var anonEnumeration =
    from post in AllPosts()
    where post.Date > oldDate
    let author = GetAuthor( post.AuthorId )
    select new { 
        PostName = post.Name, 
        post.Date, 
        AuthorName = author.Name
    };

现在看看智能感知中的anonEnumeration,它会显示类似IEnumerable<'a>

foreach( var item in anonEnumeration ) 
{
    //VS knows the type
    item.PostName; //you'll get intellisense here

    //you still have type safety
    item.ItemId;   //will throw a compiler exception
}

c#编译器非常聪明——单独生成的anon类型如果它们的属性匹配,将具有相同的生成类型。

除此之外,只要你有智能感知,在上下文清楚的地方使用var是有意义的。

//less typing, this is good
var myList = new List<UnreasonablyLongClassName>();

//also good - I can't be mistaken on type
var anotherList = GetAllOfSomeItem();

//but not here - probably best to leave single value types declared
var decimalNum = 123.456m;

我发现使用var关键字实际上使代码更具可读性,因为你只是习惯于跳过'var'关键字。当您真的不关心具体类型是什么时,您不需要一直向下滚动来弄清楚代码在做什么。如果我真的需要知道下面的“item”是什么类型,我只需将鼠标悬停在它上面,Visual Studio就会告诉我。换句话说,我更愿意读书

foreach( var item in list ) { DoWork( item ); }

一遍又一遍地

foreach( KeyValuePair<string, double> entry in list ) { DoWork( Item ); }

当我试图消化代码时。我认为这在某种程度上可以归结为个人喜好。在这一点上,我将依赖常识——在重要的方面(安全性、数据库使用、日志记录等)保留强制标准。

-工业。

考虑到智能感知现在是多么强大,我不确定var是否比在一个类中拥有成员变量或在一个方法中定义在可见屏幕区域之外的局部变量更难阅读。

如果你有一行代码,比如

IDictionary<BigClassName, SomeOtherBigClassName> nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>();

Is比以下更容易或更难读:

var nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>();

我尽可能使用var。

如果你的代码写得好,局部变量的实际类型并不重要(例如,良好的变量名,注释,清晰的结构等)。