举个例子:
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。不应该有一个程序到界面吗?
答案 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 ++等)阅读代码,那么在没有经过一些研究的情况下,你将很难找到类型。