在与同事讨论了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的使用应该与明智选择的变量名称相结合。

我在foreach语句中使用var没有问题,前提是它不是这样的:

foreach (var c in list) { ... }

如果是这样的话:

foreach (var customer in list) { ... }

... 这样,阅读代码的人就更有可能理解什么是“列表”。如果您可以控制列表变量本身的名称,那就更好了。

这同样适用于其他情况。这是非常无用的:

var x = SaveFoo(foo);

... 但这是有道理的:

var saveSucceeded = SaveFoo(foo);

各有各的,我想。我发现自己这样做,简直是疯了:

var f = (float)3;

我需要一个12步的var程序。我叫Matt,我(ab)使用var。

其他回答

var是c# 3.0和LINQ中为匿名类型引入的占位符。

因此,它允许在一个集合中为更少的列编写LINQ查询。不需要在内存中复制信息,只加载完成你需要做的事情所必需的东西。

var的使用一点也不坏,因为它实际上不是一个类型,但正如在其他地方提到的,它是一个类型的占位符,它是并且必须定义在等式的右边。然后,编译器将用类型本身替换关键字。

即使使用智能感知,当一个类型的名称很长时,它也特别有用。只需要写var,然后实例化它。之后阅读您的代码的其他程序员将很容易理解您在做什么。

就像使用

public object SomeObject { get; set; }

而不是:

public object SomeObject {
    get {
        return _someObject;
    } 
    set {
        _someObject = value;
    }
}
private object _someObject;

每个人都知道属性在做什么,就像每个人都知道var关键字在做什么一样,这两个例子都倾向于通过简化它来简化可读性,并使程序员更容易编写有效的代码。

@Keith -

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

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

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

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

我认为var的使用应该与明智选择的变量名称相结合。

我在foreach语句中使用var没有问题,前提是它不是这样的:

foreach (var c in list) { ... }

如果是这样的话:

foreach (var customer in list) { ... }

... 这样,阅读代码的人就更有可能理解什么是“列表”。如果您可以控制列表变量本身的名称,那就更好了。

这同样适用于其他情况。这是非常无用的:

var x = SaveFoo(foo);

... 但这是有道理的:

var saveSucceeded = SaveFoo(foo);

各有各的,我想。我发现自己这样做,简直是疯了:

var f = (float)3;

我需要一个12步的var程序。我叫Matt,我(ab)使用var。

我不使用var,因为它违背了c#的根- C/ c++ /Java。尽管这是一个编译器技巧,但它使语言感觉不那么强类型。也许20多年的C语言已经在我们(反变量的人)的头脑中根深蒂固了,我们应该在等号的左右两边都有类型。

话虽如此,我可以看到它对于长泛型集合定义和长类名(如codinghorror.com示例)的优点,但在其他地方,如string/int/bool,我真的看不出这一点。特别是

foreach (var s in stringArray)
{

}

节省3个字符!

对我来说,主要的烦恼是无法看到var代表方法调用的类型,除非你将鼠标悬停在方法上或F12它。

我认为人们不理解var关键字。 他们把它和Visual Basic / JavaScript关键字搞混了, 这完全是另一回事。

许多人认为var关键字意味着 弱类型(或动态类型),而实际上c#是并保持强类型。

如果你在javascript中考虑这个:

var something = 5;

你可以:

something = "hello";

在c#中,编译器会从第一条语句中推断出类型, 导致“int”类型的东西,因此会产生第二条语句 在异常中。

人们只需要明白,使用var关键字并不意味着 动态类型,然后决定var关键字的使用程度, 知道它对于将要编译的内容绝对没有区别。

当然var关键字的引入是为了支持匿名类型, 但如果你看这个:

LedDeviceController controller = new LedDeviceController("172.17.0.1");

这是非常非常冗长的,我相信这是一样可读的,如果不是更多:

var controller = new LedDeviceController("172.17.0.1");

结果是完全相同的,所以是的,我在我的代码中使用它

更新:

也许,只是也许……他们应该用另一个关键词, 那我们就不会有这样的讨论了……也许是“推断”关键字而不是“var”