我有一个树型类Foo<T>
,其接口为IFoo<T>
。
我希望Foo<T>
能够在IEquatable<Foo<T>>
时实施T : IEquatable<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>
我希望能够为IEquatable<Foo<T>>
实施Foo<T>
)?一种条件where
。FooTwo<T>
实现IEnumerable <FooTwo<T>>
Foo<T> IEnumerable
以快速简便的方式实施?编辑:
在IEquatable<Foo<T>>
的特殊情况下,我对问题1有一个简单的答案。我可以测试是否T:IEquatable<T>
并在需要时更改IEquatable<Foo<T>>
的实现。但是我仍然想知道如何在更一般的情况下这样做。
答案 0 :(得分:2)
对于问题1,你应该考虑一下你是否真的需要这个。 IEquatable<T>
mostly exists for performance reasons relating to value types。在您的情况下,您确实不应该确保使用IEquatable
等于而不是对象1。例如,Tuple<T>
就是这样。然后你可以只有一个没有约束的接口:
public interface IFoo<T> : IEnumerable<IFoo<T>>, IEquatable<IFoo<T>>
对于问题2,您可能也不需要这个。 IEnumerable<T>
为covariant,这意味着如果您有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>>
的有效实现,而File "/var/www/new-elf-lite/app/templates/base.html", line 71, in block "navbar"
{% if current_user.is_authenticated() %}
AttributeError: 'bool' object has no attribute '__call__'
也不是current_user.is_authenticated
的实现。您应该将此要求视为设计气味并尽量避免使用。
答案 1 :(得分:1)
由于您实际上正在尝试将某些IFoo<T>
个对象设为IEquatable<T>
而某些设备没有,并且这显然与类型系统不一致,我会避免IEquatable<T>
完全。使用IEqualityComparer<T>
。只需提供一种方法,在给定IEqualityComparer<IFoo<T>>
时创建IEqualityComparer<T>
(如果需要,可以使用T
的默认比较器)。
通过这样做,IFoo<T>
个对象都没有义务对自己进行比较,但只要知道如何比较底层对象,任何人都可以创建一种共同构建IFoo<T>
对象的方法。 / p>
这也完全不需要IFoo<T>
的多个实现,大大简化了整个代码库,完全消除了其他问题。
如何使用
FooTwo<T>
实现IEnumerable<FooTwo<T>>
Foo<T> IEnumerable
以快速简便的方式实施?
(如果您选择不遵循我的建议来改变您处理平等的方式:)
如果你知道序列中的所有项目实际上都是正确的类型,你可以在序列上使用Cast<FooTwo<T>>()
。
如果序列中的项目实际上不是FooTwo<T>
个对象,那么您需要将项目投影到一个新序列中,在此序列中将每个IFoo<T>
项目映射到FooTwo<T>
项目