为什么我应该使用隐式类型的局部变量?

21

当我说

public static IMyType GetGateWayManager()
{
    IUnityContainer _container = GetContainer();
    IMyType _gateWayManager = _container.Resolve<IMyType>();
    return _gateWayManager;
}

它带有一个警告,内容是 使用隐式类型的局部变量

如果我将其更改为

public static IMyType GetGateWayManager()
{
    IUnityContainer _container = GetContainer();
    var _gateWayManager = _container.Resolve<IMyType>();
    return _gateWayManager;
}

没问题。

有人能告诉我为什么 VS 编辑器认为在这里使用 var 是最佳实践吗?


4
是什么导致了这个警告?是VS编译器还是像 ReSharper 这样的外部工具? - codeulike
1
你说“失去类型”这一事实表明你可以从阅读 var 的文档中受益。它并不意味着“变量”。 - AakashM
2
肯定看起来像是Resharper的警告... - Thomas Levesque
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Kubilay Kara
6个回答

21

类型是为谁而存在的?

编译器?是的,绝对是的。编译器使用类型来确保在运行时程序能够正确运行,通过确保类型匹配、调用实际存在的方法和传递正确类型的参数来做到这一点。在这里,编译器正在检查你是否实际返回了一个 IMyType 类型的值。

编辑器?同样是的。编辑器使用后台编译和类型信息来帮助你编写代码。当你在输入_container之后输入.,它使用类型信息告诉你有一个名为Resolve的方法以及它接受哪些参数。

你自己?不是很需要。我们已经看到编译器将确保你返回IMyType类型的值,那么为什么要声明它的类型呢?编译器可以计算并为你检查它。同样地,编辑器会告诉你容器上的方法,那么为什么要声明它是 Unity 容器还是其他类型的容器呢?你已经从变量名中知道它是某种类型的容器,并且从编辑器中知道它有一个Resolve方法。

声明本地变量的类型没有问题,但ReSharper正在告诉你编译器可以计算并为你检查类型,因此它是多余的信息,并且使用隐式类型和良好的变量名能让你的代码更加清晰。例如,这段代码的目的是否比原始示例不清晰?

public static IMyType GetGateWayManager()
{
    var container = GetContainer();
    var gateWayManager = container.Resolve<IMyType>();
    return gateWayManager;
}

3
隐式类型有一个优点,那就是如果 GetContainer 的返回类型发生了变化(但签名保持不变),比如被重命名或者替换为相似的类型,上述代码就不需要进行修改来适应这种变化。(不过,需要重新构建代码)。 - Massif
是的,良好的变量名称。多么好的想法。应该避免在名称中使用不透明度。 - Allen

8

Resharper建议使用var而不是显式类型,因为它更加清晰和有用。

更加清晰,因为你所编写的代码更少,你的关注点是变量名而不是类型名。你可能认为类型名很重要,但是过了一段时间后你会忘记它。

更加有用,因为当你更改一个方法的返回类型时,你不需要更改所有的类型。

示例:

int id = getId();
List<MyType> myList = FindById(id);

在这种情况下,如果你将id从int改为guid,则必须更改此处的“int”。虽然这很小,但在实际项目中很容易变得复杂。使用var,您可以为编译器提供完全相同的代码,而不需要始终更改它。

var id = getId();
var myList = FindById(id);

我曾经更喜欢显式类型,但试用 var 几个小时后,我不会轻易放弃它。

记住:var 在编译时被更改为正确的类型。这与动态类型不同,在几乎所有情况下都不建议使用动态类型。


2
所以看看你的第二个例子,仅仅通过查看FindById方法,你能知道返回的是什么类型吗?你无法确定,这就是隐式类型的缺点。 - LarryBud

5
也许是ReSharper。
当变量类型可以在代码中看到时,ReSharper建议使用var。在您的示例中,我们可以看到_gateWayManager将是IMyType类型,然后我们使用var关键字进行隐式类型化变量。由于我们无法确定GetContainer()会返回什么类型的对象,因此_container在代码中将被明确地声明类型。

2

可能不是VS编辑器,而是ReSharper给你发出的提示信息。这更多是一种口味问题,而不是最佳实践问题。但是一旦你习惯了var关键字,你就会越来越喜欢它。至少我已经学会了爱它。


2
@ltsik - 不,这与手动声明类型没有区别。 - Greg Beech
1
@Itsik,不是动态类型,只是在编译时将被转换为正确的类型。这仅仅是一种节省程序员写出List<Dictionary<string,IEnumerable<int>>>等内容的语法糖。 - Martin Harris
不同于 .net 4 中只在运行时检查的 dynamicvar 在编译时被转换为正确类型,因此表现完全相同。如果无法确定 var 的类型,则仍会出现编译错误。 - Alex Paven
@ltsik:您可能会发现这个问题有用https://dev59.com/7nA65IYBdhLWcg3w7TWZ#3555656 - Brian Rasmussen
谢谢!我猜我应该继续阅读《深入理解C#》的第三部分了(我快要完成第二部分了)。 - Itsik

1

这是 Resharper 给你的警告,而不是 VS 编辑器。


0

已批准的答案肯定是正确的,并且回答了所描述的问题。

但是 - 我想提出一个情况,您必须使用隐式类型:当变量表示匿名类型时。

考虑以下代码:

var upperLowerWords =
    from w in words
    select new { Upper = w.ToUpper(), Lower = w.ToLower() };

upperLowerWords 应该是什么类型?你无法确定,因为没有一个明确的类型与返回值匹配 - 但编译器可以识别这种类型。实际上,它已经识别了。

参考资料:https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/implicitly-typed-local-variables(这就是我得到这个例子的地方)


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