在C#中使用类型推断有哪些优缺点?

10
我有一个同事反对在C#中使用类型推断。我认为他的大部分论点都围绕可读性不足。我的反驳是,Visual Studio的Intellisense功能提供了一种简单的查看类型的方式,从代码中阅读它们并不像我们在记事本中编码时那样必要。
然而,我对在C#中使用类型推断的优缺点很感兴趣。我来自C++,知道C++0x的“auto”具有更加客观的好处,因为你并不总是知道你得到的类型(尤其是在进行重型模板编程时)。例如,使用auto存储Boost.Bind的值。
在C#中,类型推断似乎并不像要求那样重要,更多的是一种“好用”或者说是简化语法的特性。我认为,在处理长类型时会很有用,例如:
Lazy<List<MyNamespace.ISomeVeryLongInterfaceType>> myVar = obj.GetLazy();

它将是:

var myVar = obj.GetLazy();

在我看来,这种写法更清晰。然而,是否存在关于类型推断的正面或负面的客观论据?即使在可争议的情况下(例如使用'var'代替'int'),使用它是良好的编程实践吗?

希望能有一些帮助我理解如何在日常编码中使用'var'的指导。


1
ReSharper似乎经常提示我使用var... - NickAldwin
6
请访问http://blogs.msdn.com/b/ericlippert/archive/2011/04/20/uses-and-misuses-of-implicit-typing.aspx。 - Jon Skeet
如果你问我,显式命名类型应该是非常罕见的例外,即使在这种情况下,你也应该使用可能承受得起的最通用类型。但话说回来,我主要使用Python(鸭子类型)进行编程,并且非常喜欢Haskell(类型推断)和结构化类型。 - user395760
2
每当这样的讨论出现时,我总是感到很有趣,因为例子中总是充斥着像 myVarobj.GetLazy() 这样毫无意义的名称。当你给变量起这么好的名字时,似乎一切都是个坏主意。 - Dennis Zickefoose
6个回答

9

类型推断的发明正是为了解决C++中所提到的问题,它允许创建没有类型名称的匿名类型(特别是见于Lambda和Linq)。

因此,在这种情况下,它是必需的。

在另一种情况下(当类型名称已知时),则取决于风格。当类型非常明显时,我使用var

// I like this - less duplication and easier to read
var item = new List<ComplexObjectItem>();

相比之下:

List<ComplexObjectItem> item = new List<ComplexObjectItem>();

因为它可以减少重复。然而,当类型对读者不是立即明显时,我更倾向于不使用它:
// I don't like this - I need to look up what the type is
var item = ResultOfSomeFunctionWhereICantSeeWhatItIs();

但是您的情况可能会有所不同。

4
隐式类型转换在某些情况下很有用,但在其他情况下可能会有害。Eric Lippert最近发布了一篇关于隐式类型转换的文章(隐式类型转换的用途和误用),值得一读。
需要记住的一件事是,var只是供用户使用,编译器在编译时将其转换为具体的表示形式。
唯一的缺点是在使用类的接口时。
假设GetCurrentList()返回一个IList<string>:
IEnumerable<string> list = GetCurrentList();

并且

var list = GetCurrentList();

如果不同于第二个示例,那么列表将是一个IList<string>

我倾向于使用显式类型,并且通常只在代码的可读性有帮助时使用var,以及在使用匿名类型时(因为此时必须这样做)。


4
我是一位有用的助手,可以为您进行文本翻译。以下是需要翻译的内容:

我认为常识决定了以下非正式规则:

如果有一些长名称,例如:

Lazy<List<MyNamespace.ISomeVeryLongInterfaceType>> myVar = new Lazy<List<MyNamespace.ISomeVeryLongInterfaceType>>();

将其替换为

,这与编程有关,并保留HTML格式。
var myVar = new Lazy<List<MyNamespace.ISomeVeryLongInterfaceType>>();

这是有意义的,因为你仍然可以知道对象是什么。 另一方面,如果某物含糊不清,可能不应使用 var
Lazy<List<MyNamespace.ISomeVeryLongInterfaceType>> myVar = doProcess();

2
var myVar = obj.GetLazy();

在intellisense的帮助下,这种类型的推断是一个比较好的想法或者说还可以。然而如果没有intellisense,我不认为这是一个好主意,相反会成为一场噩梦。没有intellisense,由于缺乏intellisense和确切的类型,我相信大多数开发人员都会不喜欢它。

然而,即使没有intellisense,以下内容仍然很好:

var obj = new Lazy<List<MyNamespace.ISomeVeryLongInterfaceType>();

在这种情况下,类型推断非常有用,它可以避免大量的输入和重复的输入!无论是否使用智能感知,我更喜欢写:
Lazy<List<MyNamespace.ISomeVeryLongInterfaceType> obj= obj.GetLazy();

2
即使有智能提示,也不清楚正在检索哪种类型,如果有人可以瞥一眼代码并知道正在发生什么,那肯定更好。如果一个方法中有10行代码,就必须逐个悬停在每个对象上/为每个出现这种情况的行获取智能提示 - 如果我不得不这样做,我会很恼火。 - jcvandan

2

我喜欢使用类型推断来使代码更加简洁,但只有在可以在同一行看到类型时才会使用它,例如:

var myClass = new MyClass();

但是

MyClass myClass = RandomFuncThatGetsObject();

我认为在第一个例子中使用var不会影响可读性,事实上它使得代码更易读。然而,在第二个例子中使用var将会影响可读性。


2

当您使用匿名类型时,类型推断是必要的:

var x = new { Greeting = "Hello", Name = "World" };

当您使用LINQ查询时,通常始终使用匿名类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接