方法声明的返回类型应该是接口还是具体类

本文关键字:接口 声明 返回类型 方法 | 更新日期: 2023-09-27 18:26:56

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

但在某些情况下,看起来混凝土类更好。例如,

public string Replace(string old, string new)

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

我的问题是

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

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

方法声明的返回类型应该是接口还是具体类

这取决于情况。

这个问题我已经问过好几次了,这里有一个很好的例子来说明"取决于"的答案。

考虑以下类别:

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)。什么是最好的方法?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>,因为绑定系统实际上需要ObservableCollection类的方法/属性/行为(IEnumerable不足以使绑定工作)。

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

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

然而,当我在类(如数据层)之间编写一个更解耦的接口时,我总是倾向于返回最低的公共分母(例如IEnumculable),并允许我可能不知道的消费者决定如何处理它。

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

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

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

取决于您想给代码用户多少访问权限

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

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

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

  • 你们可以更好地控制你们对外部世界的访问
  • 您可以隐藏实现细节(对于该实例,即使您的类也可以保留在程序集内部)
  • 它符合接口分离原则(只通过返回和实现正确的接口来公开您想要的行为)

顺便说一句,返回"string"的例子没有多大用处。它是一个基元数据类型(我指的是mscorlib中的原生数据类型),在这个对象中没有太多可隐藏/显示的内容。