C# 中类型推断的优点和缺点是什么?

What are some advantages & disadvantages of type inference in C#?

本文关键字:缺点 是什么 类型      更新时间:2023-10-16

我有一个反对C#类型推断的同事。我相信他的大部分论点都围绕着缺乏可读性。我反对这一点的论点是,Visual Studio 的智能感知功能提供了一种查看类型的简单方法,并且从代码中读取它们并不像我们在记事本中编码那样必要。

但是,我对在 C# 中使用类型推断的优缺点感到好奇。我来自C++,我知道C++0x的"auto"有一个更客观的好处,因为你并不总是知道你得到的类型(特别是在进行繁重的模板编程时)。例如,使用 auto 来存储 Boost.Bind 的值。

在 C# 中,类型推断似乎并不那么重要,因为它是一个"很高兴拥有"或糖衣功能。我认为当您处理长类型时,它会很有用,例如:

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

它将是:

var myVar = obj.GetLazy();

在我看来,这要干净得多。但是,是否有任何客观的论据支持OR反对类型推断?使用它是否是一种良好的编程实践,即使在有争议的情况下它没有提供任何好处(例如,使用"var"而不是"int")?

在理解我应该如何在日常编码中使用"var"方面有一些帮助会很棒。

类型推断的发明正是出于您给出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();

但您的里程可能会有所不同。

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

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

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

然后将其替换为

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

这是有道理的,因为你仍然可以分辨出对象是什么。

另一方面,模棱两可的东西可能需要不使用var

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

隐式类型在某些情况下可能有用,但在其他情况下有害。Eric Lippert最近发表了一篇关于隐式类型的使用和误用的文章,值得一读。

要记住的一件事是,var仅适用于用户,编译器在编译时会将其转换为其具体表示形式。

一个缺点是使用类中的接口时。

假设GetCurrentList()返回一个IList<string>

IEnumerable<string> list = GetCurrentList();

var list = GetCurrentList();

与第二个示例中不同,列表将是一个IList<string>

我倾向于使用引出类型,通常只在有助于代码的可读性和匿名类型时使用var(因为此时您必须这样做)。

我喜欢

使用类型推断来使代码更简洁,但是我只在可以看到它在同一行上的类型时才使用它,例如:

var myClass = new MyClass();

MyClass myClass = RandomFuncThatGetsObject();

我认为在第一个示例中使用 var 不会影响可读性,实际上它使其更具可读性,但是在第二个示例中使用 var 会影响可读性。

使用匿名类型时,类型推断是必需的:

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

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

var myVar = obj.GetLazy();

在智能感知的存在下,这种类型推断是一个大致的好主意,或者说没问题。但是,如果没有智能感,那么我不会认为这是一个好主意。这将是一场噩梦。如果没有智能感知,我相信大多数开发人员会不喜欢它,因为缺乏智能感知(和确切类型,两者兼而有之)会带来不便。

但是,即使没有智能感知,以下内容也会很好:

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

在这种情况下,类型推断是一种解脱,因为它避免了大量的键入和重复键入!

无论有没有智能感知,我更喜欢写:

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