当存在接口和实现时,Var关键字类型推断歧义

时间:2009-08-11 04:49:21

标签: c#

举个例子:

interface IEntity {
    string Name { get; set; }
}

class Product : IEntity {
    public string Name { get; set; }
    public int Count { get; set; } // added member
}

class Client {
    void Process() {
        var product = new Product();
        int count = product.Count; // this is valid            

    }
}

在上面的例子中,产品的类型是什么?是IEntity还是产品?看来产品是具体实施类型(产品)。如果是这种情况,则不应仅在特殊情况下使用var。但我发现像resharper这样的工具建议默认使用var。不应该有一个程序到界面吗?

6 个答案:

答案 0 :(得分:7)

如果您仍在实例化方法中的具体类,那么您实际上并不是“编程到接口”,因为依赖于具体的Product类仍然存在。为了正确编程到接口,必须删除 new 实例,例如使用工厂或IoC。

答案 1 :(得分:6)

如果您有类似......的产品怎么办?

class Product : IFirst, ISecond, IThrid

编译器可以做的唯一合理的事情是它的作用。我不限制使用var,我到处使用它。我认为它使代码更具可读性。在这种情况下,我全面同意ReSharper。

答案 2 :(得分:4)

如果您希望Product属于IEntity类型,请尝试以下操作:

var product = new Product() as IEntity;

那就是说,是的,你应该编程到一个接口,但在你的情况下,你直接实例化具体类型。如果您已经创建了对具体类型的依赖项,只需使用具体类型。如果没有,请使用工厂或注入来获取接口的实例。 var会很好地与这些人合作。例如:

public class MyExtremelySimpleFactoryExampleClass
{
  public IEntity Instantiate()
  {
    return new Product();
  }
}

// elsewhere in your code...
var item = myFactory.Instantiate(); // item is of type IEntity

最后,不,我不认为var只应在“特殊情况”下使用。我发现它非常有用并且几乎总是使用它。

答案 3 :(得分:1)

var product = new Product()的类型为Product。如果您没有使用该接口之外的成员(Product.Count不在IEntity接口上),您可以编程到接口。

<强>加了:

此外,在VS2008中,您可以将鼠标悬停在声明中的var关键字上以查看隐含类型。此悬停/工具提示消息也适用于声明行之后的变量名称。 (来自C# In Depth,第211页)

答案 4 :(得分:1)

推断的类型是实际类型,而不是它可以实现/继承的任何接口或基类。

考虑一下:

var answer = "42";

如果它推断的是接口而不是类型,那么变量类型就像IComparable而不是string

var关键字的使用依赖于它推断实际类型,或者将其用于除匿名类型之外的任何其他内容都没有意义。只要类型很明显,您就可以使用它来使代码更具可读性,但如果类型不是很明显,则应避免使用它。 (我上面的示例位于灰色区域,因为它实际上不包含string类型名称。)

答案 5 :(得分:0)

如果您在此实例中使用var,则其类型为Product。我不喜欢默认使用var,因为它有时会使阅读代码有点混乱。

我更喜欢在var次查询中使用LINQ,但请尽量不要在其他地方过度使用(例如您的示例)。对于使用具有智能感知功能的IDE的用户来说这很好,但是如果你用记事本(或Notepad ++等)阅读代码,那么在没有经过一些研究的情况下,你将很难找到类型。