我有一个a<;T>;: ;IEnumerable<;T>;,我想添加IEquatable<;
本文关键字:lt gt 添加 IEquatable IEnumerable 有一个 #160 | 更新日期: 2023-09-27 18:29:22
我有一个Tree类型的类Foo<T>
及其接口IFoo<T>
。
我希望Foo<T>
能够在T : IEquatable<T>
时实现IEquatable<Foo<T>>
(或者更一般地,如果T : I<T>
,我可能希望Foo<T> : I<Foo<T>>
以及其他实现的接口)。
我尝试了以下伪代码:
public interface IFoo<T> : IEnumerable<IFoo<T>>
...
public class Foo<T> : IFoo<T>
...
public interface IFooTwo<T> : IFoo<T>, IEquatable<IFooTwo<T>>
where T : IEquatable<T>
...
public class FooTwo<T> : IFooTwo<T> {
... // I implement Equals
public bool NewMethod(FooTwo<T> Other) { ... }
}
所以现在我已经成功地实现了Equals
(我还推翻了geniric Equals等)
但是FooTwo<T>
现在不实现IEnumerable<IFooTwo<T>>
(而是实现IEnumerable<IFoo<T>>
)。
所以我有两个问题:
- 有没有更好的方法来组织我的代码以实现我的目标(如果
T : IEquatable<T>
,我希望能够为Foo<T>
实现IEquatable<Foo<T>>
)?一类条件CCD_ 15 - 如何使用使
FooTwo<T>
实现IEnumerable <FooTwo<T>>
Foo<T> IEnumerable
的快速简便实现
编辑:
在IEquatable<Foo<T>>
的特殊情况下,我对问题1有一个简单的答案。我可以测试是否为T:IEquatable<T>
,并在需要时更改IEquatable<Foo<T>>
的实现。然而,我仍然想知道如何在更普遍的情况下做到这一点。
对于问题1,您应该考虑是否真的需要这个。CCD_ 22的存在主要是由于与值类型相关的性能原因。在您的情况下,应该没有任何理由需要确保您使用的是IEquatable
equals,而不是对象。例如,Tuple<T>
就是这样做的。然后你就可以有一个没有限制的单一界面:
public interface IFoo<T> : IEnumerable<IFoo<T>>, IEquatable<IFoo<T>>
对于问题2,您可能也不需要这个。IEnumerable<T>
是协变的,这意味着如果您有IEnumerable<A>
,您可以将其分配给类型为IEnumerable<B>
的变量,只要A
可以分配给B
即可。在您的情况下,这意味着如果您有,例如,一个采用IEnumerable<IFoo<T>>
的方法也将接受IEnumerable<IFooTwo<T>>
,因为IFooTwo<T> : IFoo<T>
但是,如果您想使类MyFoo<T> : IFoo<T>
的类型为IEnumerable<MyFoo<T>>
,则无法自动执行此操作。这是因为完全有可能拥有IEnumerable<IFoo<T>>
的有效实现,而不是IEnumerable<MyFoo<T>>
的实现。您可能应该将此需求视为一种设计气味,并尽量避免它。
由于您主要要做的是尝试让一些IFoo<T>
对象是IEquatable<T>
,而另一些对象不是,这显然与类型系统不一致,因此我会完全避免IEquatable<T>
。使用IEqualityComparer<T>
。只需提供一个方法,在给定IEqualityComparer<T>
时创建IEqualityComparer<IFoo<T>>
(如果需要,可以使用T
的默认比较器)。
通过这样做,任何IFoo<T>
对象都没有义务进行自身比较,但只要知道如何比较底层对象,任何人都可以创建一种方法来管理IFoo<T>
对象。
这也完全消除了对IFoo<T>
的多个实现的需要,极大地简化了整个代码库,并完全消除了您的其他问题。
如何使用使
FooTwo<T>
实现IEnumerable<FooTwo<T>>
Foo<T> IEnumerable
的快速简便实现?
(如果你选择不按照我的建议改变你处理平等的方式:)
如果您知道序列中的所有项目实际上都是正确的类型,那么您可以简单地在序列上使用Cast<FooTwo<T>>()
。
如果序列中的项目实际上不是FooTwo<T>
对象,那么您需要将这些项目投影到一个新的序列中,在该序列中将每个IFoo<T>
项目映射到一个FooTwo<T>
项目。