在一般情况下,界面或抽象类通常是适当的决定,我是对的吗?
但在某些情况下,看起来具体的课程更好。例如,
public string Replace(string old, string new)
Replace
的{{1}}方法返回一个具体的类。 (这只是一个例子,虽然String没有实现任何接口。)
我的问题是
我什么时候应该返回一个界面,什么时候应该返回一个具体的类?
它是String
的一部分,用于返回界面吗?
答案 0 :(得分: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
返回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 :(得分:3)
在我看来,这取决于你是否有一种方法以紧密耦合的方式使用,即Class 1在类2上调用方法A并且总是想要某种类型,并且是唯一一次调用该方法然后你可以争辩说没有意义。一个例子可能是返回IEnumerable,其中方法将集合创建为列表,然后将其作为IEnumerable返回,然后Class 1将其作为列表使用,因此无论如何返回都需要调用ToList()。
然而,当我在诸如数据层之类的类之间编写更多的解耦接口时,我总是更喜欢返回最低的公共denomnator(例如IEnumarable)并允许我可能不知道决定做什么的消费者用它。
答案 2 :(得分:1)
我相信你错了Program to an interface, not an implementation
。 GOF通过程序对接口的意思是该类型的接口。
它们将对象的接口定义为从外部可见的所有方法。因此,在这种情况下,它们对接口的定义与您在C#中的定义不同。
关于你的问题,我认为返回抽象类可能更好。如果你返回从该抽象类派生的任何对象,它会工作吗?如果是,则返回抽象类。 如果没有,请更具体,并返回派生类型。
答案 3 :(得分:0)
取决于您希望为代码用户提供多少访问!
我的意思是,向用户返回List<AccountStatement>
没有任何意义。因为,您不希望代码的用户在此集合中添加新语句(应在预订特定事务时创建语句)
因此,在这种情况下,您可能只返回IEnumerable<AccountStatement>
- 只读取访问权限。
一般来说,我支持从方法返回接口的想法,原因如下:
顺便说一句,你返回“字符串”的例子没什么用。它是一种原始数据类型(我的意思是mscorlib中的本机数据类型),并且在此对象中隐藏/显示的内容并不多。