什么时候我应该提供一个接口的通用和非通用版本

本文关键字:接口 版本 一个 我应该 什么时候 | 更新日期: 2023-09-27 18:10:31

我理解对象的深层克隆和浅层克隆之间的区别,但根据Simon对这个(复制构造函数与克隆)问题的回答,应该提供一个泛型和非泛型版本。为什么?

可以定义两个接口,一个带泛型参数以支持强类型克隆,另一个不带泛型参数以保留弱类型克隆能力,以便在处理不同类型可克隆对象的集合时使用:

我的意思是,制作不同的接口已经足够琐碎了,但是在现代c#的泛型范式中,我发现很难想出一个合理的理由,为什么要使用非泛型和弱类型的版本。见鬼,你甚至可以有T:object做同样的事情!

我会这样写我的接口:

public interface IShallowCloneable
{
    object Clone();
}
public interface IShallowCloneable<T> // Should this derive IShallowCloneable?
{
    T Clone();
}
public interface IDeepCloneable
{
    object Clone();
}
public interface IDeepCloneable<T> // Should this derive IDeepCloneable?
{
    T Clone();
}

我的类会这样实现它:

public class FooClass : IDeepCloneable<FooClass>
{
    // Implementation
}

什么时候我应该提供一个接口的通用和非通用版本

正如上面引用的那样,如果您希望能够使用由相同泛型定义产生的泛型类型集合,但具有不同的类型参数,那么您确实必须提供一个非泛型接口。

考虑IDeepCloneable<Widget>IDeepCloneable<Gadget>实例的列表。您总是可以将其设置为List<object>,但是这样您就不能克隆它们,除非您诉诸于运行时类型检查。

如果您希望能够以多态方式克隆(或通常以其他方式访问)这些项,则需要对它们进行类型化,以便它们的静态类型提供允许您完成该工作的最小公共接口。在本例中,这将使我们的列表为List<IDeepCloneable>

如果你不打算多态地使用这些接口,那么拥有一个非通用的IDeepCloneable并不能提供任何东西。

你回答了你自己的问题。:)

你需要非泛型版本来处理非泛型集合。

IEnumerableIEnumerable<T>接口为例。泛型接口实现非泛型接口,但仅提供与非泛型集合的向后兼容性:

理想情况下,所有的通用集合接口(例如ICollection<T>IList<T>)将从它们的非泛型对应物继承,这样泛型接口实例可用于泛型和非泛型代码。例如,如果使用IList<T>可以传递给需要illist的代码