关于c#:方法声明的返回类型应该是接口还是具体类?

Should the return type of a method declaration be interface or concrete class?

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

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

1
public string Replace(string old, string new)

StringReplace方法返回一个具体类。(这只是一个示例,尽管字符串不实现任何接口。)

我的问题是

  • 什么时候返回接口,什么时候返回具体类?

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


  • 这要看情况而定。

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

    考虑以下类别:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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的对象。这是对返回对象的完全不同的利用。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    private static void Main(string[] args)
    {
        foreach (var z in MyClass.Test())
        {
            Console.WriteLine(z);
        }

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

        Console.ReadKey();
    }

    如果希望开发人员只在枚举中使用返回的对象,那么可以使用该接口作为返回类型。如果希望开发人员使用接口具体实现的方法/属性(在上面的示例中,通过索引访问对象),那么可以返回具体类型。

    还要记住,有时候你别无选择。例如,如果要公开一个应用于Silverlight绑定的公共集合,则应返回ObservableCollection,而不是IEnumerable,因为绑定系统实际上需要ObservableCollection类的方法/属性/行为(IEnumerable不足以使绑定工作)。

    您应该避免的是每次返回IEnumerable的方法,该方法与ToList()一起使用。


    在我看来,这取决于,假设您有一个以紧密耦合的方式使用的方法,也就是说,类1在类2上调用方法A,并且总是需要某种类型,并且是唯一一次调用该方法,那么您可以说没有意义。例如,返回IEnumerable,方法将集合创建为一个列表,然后将其作为IEnumerable返回,然后类1将其作为一个列表使用,因此无论如何都需要调用ToList()。

    但是,当我在类(如数据层)之间编写一个更为解耦的接口时,我总是倾向于返回最低的公共去噪器(例如IEnumable),并允许我可能不知道如何处理它的使用者。


    我相信你弄错了。gof的意思是程序到接口,是类型的接口。

    它们将对象的接口定义为从外部可见的所有方法。因此,在本例中,它们对接口的定义不同于您在C中的定义。

    关于您的问题,我相信返回抽象类可能更好。如果您返回从该抽象类派生的任何对象,它会工作吗?如果是,则返回抽象类。如果不是,则执行更具体的操作,并返回派生类型。


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

    我的意思是,把List返回给用户毫无意义。因为,您不希望代码的用户在此集合中添加新语句(应在预订特定事务时创建语句)

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

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

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

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