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


当前回答

在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 sb = new StringBuilder();

而不是:

StringBuilder sb = new StringBuilder();

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

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

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

我认为VAR的关键是只在适当的地方使用它,即在Linq中做一些方便的事情(可能在其他情况下)。

如果你有一个类型的东西,那么你应该使用它-不这样做是简单的懒惰(与创造性的懒惰相反,这通常是被鼓励的-优秀的程序员往往非常努力地工作,懒惰,可以被认为是最初的东西的来源)。

全面禁止就像滥用这种结构一样糟糕,但确实需要一个合理的编码标准。

另一件需要记住的事情是,它不是VB类型变量,因为它不能改变类型——它是一个强类型变量,它只是类型是推断出来的(这就是为什么有人会认为在foreach中使用它不是不合理的,但出于可读性和可维护性的原因,我不同意)。

我怀疑这个会一直持续下去(-:

梅菲

当你不想重复自己的时候,Var很有用。例如,我昨天需要一个类似于此的数据结构。您喜欢哪种表示法?

Dictionary<string, Dictionary<string, List<MyNewType>>> collection = new Dictionary<string, Dictionary<string, List<MyNewType>>>();

or

var collection = new Dictionary<string, Dictionary<string, List<MyNewType>>>();

请注意,在本例中使用var几乎不会引起歧义。然而,有时候这并不是一个好主意。例如,如果我像下面这样使用var,

var value= 5;

当我可以只写真正的类型,并消除任何歧义5应该如何表示。

double value = 5;

在测试过程中,我发现自己的代码是这样的:

var something = myObject.SomeProperty.SomeOtherThing.CallMethod();
Console.WriteLine(something);

现在,有时,我想看看SomeOtherThing本身包含什么,SomeOtherThing不是CallMethod()返回的相同类型。因为我使用了var,我只是改变了这个:

var something = myObject.SomeProperty.SomeOtherThing.CallMethod();

:

var something = myObject.SomeProperty.SomeOtherThing;

如果没有var,我也必须不断改变左边声明的类型。我知道这是小事,但它非常方便。

Kronoz -在这种情况下(两者都重载)会有问题吗?如果你有两个不同类型的重载,本质上你会说任何一个都可以被传递,做同样的事情。

不应该有两个重载根据传递的类型执行完全不同的操作。

虽然在这种情况下您可能会感到困惑,但它仍然是完全类型安全的,只是有人调用了错误的方法。