2012-03-07 81 views
12

在一般情况下,界面或抽象类往往是适当的决定,我是对吗?方法声明的返回类型应该是接口还是具体类?

但在某些情况下,它看起来像具体的类更好。例如,

public string Replace(string old, string new) 

String的的Replace方法返回的具体类。 (这只是一个例子,尽管字符串没有实现任何接口。)

我的问题是

  1. 当我应该返回一个接口,当我应该返回的具体类?

  2. 是否返回界面program to an interface, not an implementation的一部分?

回答

4

这取决于。

我已经看到了这个问题问了几次,这里是一个很好的例子,来说明“这取决于”的答案。

考虑下面的类:

public class MyClass 
{ 
    public static IEnumerable<int> Test() 
    { 
     return new List<int> { 2, 3, 4 }; 
    } 

    public static List<int> Test2() 
    { 
     return new List<int> { 2, 3, 4 }; 
    } 
} 

Test返回IEnumerableTest2返回一个具体实现IEnumerable接口(List在这种情况下)的。什么是最好的方法? TestTest2

事实上,无论是在语义上是不同的:

  • 作为Test只返回一个IEnumerable,它意味着,它的合同的方法,开发人员使用返回的对象枚举的一部分(foreach )。
  • 由于Test2返回List实例,它允许用户通过索引访问List的对象。这与返回的对象完全不同。

private static void Main(string[] args) 
{ 
    foreach (var z in MyClass.Test()) 
    { 
     Console.WriteLine(z); 
    } 

    var f = MyClass.Test2()[0]; 

    Console.ReadKey(); 
} 

如果你希望开发者使用返回的对象枚举只,那么你可以使用接口作为返回类型。如果你希望开发者使用方法/具体实施的接口的属性(在上面的例子中,访问由索引对象),那么你可以返回一个具体类型。

还记得,有时候你别无选择。例如,如果要公开应当用于为Silverlight结合公开征集,那么你就应该返回ObservableCollection<T>,不IEnumerable<T>,因为结合系统实际需要ObservableCollection类的方法/属性/行为(IEnumerable会不会足以让绑定工作)。

你应该避免的是一种方法,返回IEnumerable<T>并且每次与ToList()一起使用。

+0

我讨厌那些返回IEnumerable 的方法,当我们得到的是一个List 。我不能使用常规for循环(参考项与其索引),或者甚至调用最简单的Count方法(不使用LINQ Count方法)。当我所做的只是返回一个列表时,我使用的返回类型是IList 。与收益回报结合使用时,我只/大部分会返回IEnumerable 。一个注释:在开发公共图书馆时,使用IEnumerable可能会有更多优势。 – Nullius 2015-11-02 13:23:46

1

您正在收到Program to an interface, not an implementation错误,我相信。 GOF的意思是程序对接口的意义是类型的接口。

它们将对象的接口定义为从外部可见的所有方法。因此,在这种情况下,它们的接口定义与您在C#中的定义不同。

关于你的问题,我会认为返回抽象类可能会更好。如果您返回从该抽象类派生的任何对象,它会起作用吗?如果是,则返回抽象类。 如果不是,则更具体,并返回派生类型。

+0

有关“计划到inferface'设计princible更多信息,看看他的专访埃里希的Gamme:http://www.artima.com/lejava/articles/designprinciples。html – sloth 2012-03-07 09:19:08

+0

@squelos我不是指'编程接口'只是返回一个方法的接口。我的意思是当你的API返回一个接口时,使用你的API的用户可以做'编程到接口'。如果你返回一个具体的类,你不能'强迫'你的用户使用接口。 – 2012-03-08 02:18:57

+0

噢,我错了。我对“界面”所理解的内容有所怀疑,所以我首选澄清。没问题,然后 – squelos 2012-03-08 08:06:01

3

在我看来,这取决于说,如果你有在紧密耦合方式使用的方法,对2级,即1所调用方法A和总是想某种类型并调用该方法,那么唯一的一次你可以争辩说没有意义。这方面的一个例子可以返回IEnumerable的,该方法创建集合为一个列表,然后返回它为IEnumerable,1级,然后消耗,作为一个列表反正这样的回报都要ToList()被在其反正叫。

然而,当我在诸如数据层之类的类之间写入一个更加分离的接口时,我总是更愿意返回最低的通用denomnator(例如IEnumarable),并允许我可能不知道的消费者决定什么用它做。

0

取决于你想要多少访问给你的代码的用户!

我的意思是,返回List<AccountStatement>用户将没有任何意义。因为,您不希望您的代码的用户在此集合中添加新语句(在预订特定事务时应创建一条语句)

因此,在这种情况下,您可能只返回IEnumerable<AccountStatement> - 只读访问。

一般来说,我支持恢复从方法接口的理由如下的想法:

  • 您在访问得到较好的控制,你给你的对象到外面的世界。
  • 你到隐藏实施细则(适用于例如,即使你的类可以保持内部组装)
  • 它是在线与接口分离原则(仅暴露希望通过返回的行为,并实施,正确的界面)。

顺便说一句,你返回“字符串”的例子没有多大用处。它是一种原始数据类型(我的意思是mscorlib中的一种本地数据类型),并且在这个对象中隐藏/显示的内容并不多。

+0

erm ...字符串不是原始类型。 – Sinaesthetic 2012-07-06 04:06:58

+0

添加更正声明。我的意思是它是一种本地常用数据类型。 – 2012-07-10 04:00:12

相关问题