假设我有一个带共享接口的简单继承结构:
public interface IMammal
{
...
}
public class Human : IMammal
{
...
}
public class Animal : IMammal
{
...
}
并且在另一个类(Main.cs或其他)中说,我想实现一个方法。以下哪项是“最佳实践”:
public void MyFunction(IMammal input)
{
// Do cool things with the IMammal.
}
或者
public void MyFunction<T>(T input) where T : IMammal
{
// Do the same cool things with the IMammal.
}
注意:在这个简单的情况下,一个可能的解决方案是使IMammal成为一个抽象类,并在该抽象类中实现MyFunction。我需要保持IMammal接口。
答案 0 :(得分:2)
最佳实践通常是第一种情况,并让底层运行时的多态行为为您处理类型。除非你特别需要知道类型(以及作为通用!),否则最好不要传递它。
第二个选项的情况是在你打算调用其他需要通用的方法时,例如那些操纵集合或序列化,以及必须处理T
的方法对象的实际类型。然而,这是非常罕见且非常特殊的行为,所以最好只在绝对必要时使用它。
答案 1 :(得分:1)
这取决于MyFunction
做什么。如果MyFunction
的工作原理与没有泛型的设计相同,那么请保持这种方式 - 使用多态通常比引入泛型更清晰。如果您使用泛型是有益的(例如添加到List<T>
而不是List<Mammal>
,那么请切换到泛型。
创建工作的代码,然后专注于使其更好。
答案 2 :(得分:0)
我认为第一个更好,我的意思是,如果你正在调用其他类,你应该通过接口而不是类。
public void MyFunction(Mammal input)
{
// Do cool things with the mammal.
}
此外,最好将接口称为IMammal而不是哺乳动物。
那是因为MyFunction是另一个类的方法,根据最佳实践,最好是注入一个接口而不是一个对象。
答案 3 :(得分:0)
在您的特定情况下,我通常会选择第一个选项。
但是,对于更复杂的场景,第二个选项更好,因为它允许您进一步指定类型约束,例如从多个接口继承,或者类和接口等。
例如,如果您还在方法的new()
子句中包含where
,它还允许您实例化新的T对象。
答案 4 :(得分:0)
我看到两个实现是等价的。那么简单就是最好的,所以选择#1我更喜欢。
如果MyFunction是Mammal的行为,它应该在界面中。如果你做了一些验证,例如并且需要更高层的其他东西,那么把它放在其他类中应该很好。