C# · 12月 22, 2021

c# – 将类型约束到接口的目的是什么?

允许以下内容的目的是什么? class A<T> where T : IFoo { private T t; A(T t) { this.t = t; } /* etc */}

这有什么意义上的区别只是声明A需要一个IFoo,只要它需要一个?

class A { private IFoo foo; A(IFoo foo) { this.foo = foo; } /* etc */}

我能看到的唯一区别是,在第一种情况下,我保证A< T>将始终使用实现IFoo的T进行实例化,并且A中的所有对象将具有相同的基本类型.但对于我的生活,我无法弄清楚为什么我需要这样的约束.

解决方法 编辑:起初我以为你是愚蠢的:第一个例子肯定不会编译.只有在自己尝试之后(看到它确实编译)我才意识到 Doggett already pointed out:你的B级< IFoo>示例实际上与IFoo接口没有关系;它只是一个泛型类型,其类型参数恰好称为IFoo.

也许你已经意识到了这一点,你真的在​​问:“为什么我要想限制泛型类型参数呢?”如果是这种情况,那么我认为其他答案在某种程度上已经解决了这个问题.但听起来好像你在问,“为什么我会这样定义我的类型,而不是像这样(因为它们实际上是一样的)?”答案很简单:它们不一样.

现在,这是另一个问题 – 一个你没有问的问题,但是我最初想要回答的问题;)

为什么要定义这样的类型:

class A<T> where T : IFoo{ T GetFoo();}

……而不是这个?

class A{ IFoo GetFoo();}

这是我想到的一个原因(因为它类似于我过去处理过的场景):你设计的不是一个类,而是一个小的层次结构,而IFoo只是你所有的“基线”界面类需要,而有些可能会利用特定的实现,或更多的派生接口.

这是一个愚蠢的例子:

class SortedListBase<T,TList> where TList : IList<T>,new(){ protected TList _list = new TList(); // Here’s a method I can provide using any IList<T> implementation. public T this[int index] { get { return _list[index]; } } // Here’s one way I can ensure the list is always sorted. Better ways // might be available for certain IList<T> implementations… public virtual void Add(T item) { IComparer<T> comparer = Comparer<T>.Default; for (int i = 0; i < _list.Count; ++i) { if (comparer.Compare(item,_list[i]) < 0) { _list.Insert(i,item); return; } } _list.Add(item); }}class SortedList<T> : SortedListBase<T,List<T>>{ // Here is a smarter implementation,dependent on List<T>’s // BinarySearch method. Note that this implementation would not // be possible (or anyway,would be less direct) if SortedListBase’s // _list member were simply defined as IList<T>. public override void Add(T item) { int insertionIndex = _list.BinarySearch(item); if (insertionIndex < 0) { insertionIndex = ~insertionIndex; } _list.Insert(insertionIndex,item); }}