方法声明的返回类型应该是接口还是具体类
本文关键字:接口 声明 返回类型 方法 | 更新日期: 2023-09-27 18:26:56
在一般情况下,接口或抽象类通常是合适的决定,对吗?
但在某些情况下,看起来混凝土类更好。例如,
public string Replace(string old, string new)
String
的Replace
方法返回一个具体类。(这只是一个例子,尽管String没有实现任何接口。)
我的问题是
我应该什么时候返回接口,什么时候返回具体类?
它是否是
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
返回IEnumerable
,Test2
返回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中的原生数据类型),在这个对象中没有太多可隐藏/显示的内容。