14

在一般情况下,接口或抽象类通常是合适的决定,对吗?

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

public string Replace(string old, string new)

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

我的问题是

  1. 什么时候应该返回一个接口,什么时候应该返回一个具体的类?

  2. 它是program to an interface, not an implementation返回接口的一部分吗?

4

4 回答 4

5

这取决于。

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

考虑以下类:

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返回接口的具体实现IEnumerableList在这种情况下)。最好的方法是什么?Test还是Test2

实际上,两者在语义上是不同的:

  • 由于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>,因为绑定系统实际上需要类的方法/属性/行为ObservableCollectionIEnumerable对于绑定来说是不够的去工作)。

您应该避免的是每次IEnumerable<T>都使用返回的方法。ToList()

于 2012-03-07T09:38:33.480 回答
3

在我看来,这取决于,如果你有一个以紧密耦合方式使用的方法,即 Class 1 在 Class 2 上调用 Method A 并且总是想要某种类型并且是唯一一次调用该方法,那么你可以在那里争论没有意义。这方面的一个示例可能是返回 IEnumerable,其中该方法将集合创建为列表,然后将其作为 IEnumerable 返回,然后类 1 无论如何都会将其作为列表使用,因此无论如何都需要调用返回的 ToList()。

但是,当我在类之间编写更解耦的接口(例如数据层)时,我总是更喜欢返回最低公分母(例如 IEnumarable)并允许我可能不知道如何处理它的消费者。

于 2012-03-07T09:16:33.017 回答
1

我相信你Program to an interface, not an implementation错了。GOF所说的程序对接口的意思,就是接口的类型。

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

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

于 2012-03-07T09:08:15.440 回答
0

取决于您想为代码的用户提供多少访问权限!

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

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

一般来说,我确实支持从方法返回接口的想法,原因如下:

  • 您可以更好地控制向外部世界授予对象的访问权限。
  • 您可以隐藏实现细节(例如,即使您的类也可以保留在程序集内部)
  • It is in-line with Interface Segregation Principle (only expose the behavior you want by returning, and implementing, the right interface).

Btw, your example of returning "string" is not of much use. It is a primitive data type (I mean a native data type in mscorlib), and there is not much to hide/show in this object.

于 2012-03-07T10:17:07.643 回答