我有一个A <t>类:IEnumerable <t>,我想添加IEquatable <a <t>&gt;如果T:IEquatable <t>。我怎么能这样做并保持IEnumerable?

时间:2016-01-06 13:15:13

标签: c# inheritance interface

我有一个树型类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>>)。

所以我有两个问题:

  1. 我是否有更好的方法来组织我的代码以实现我的目标(如果T : IEquatable<T>我希望能够为IEquatable<Foo<T>>实施Foo<T>)?一种条件where
  2. 如何使用FooTwo<T>实现IEnumerable <FooTwo<T>> Foo<T> IEnumerable以快速简便的方式实施?
  3. 编辑:

    IEquatable<Foo<T>>的特殊情况下,我对问题1有一个简单的答案。我可以测试是否T:IEquatable<T>并在需要时更改IEquatable<Foo<T>>的实现。但是我仍然想知道如何在更一般的情况下这样做。

2 个答案:

答案 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>项目