C# 我有一个a级<;T>;: ;IEnumerable<;T>;,我想添加IEquatable<;A<;T>&燃气轮机;如果T ;: ;IEquatable<;T>;。我如何才能做到这一点,并保持IEnumerable以及?

C# 我有一个a级<;T>;: ;IEnumerable<;T>;,我想添加IEquatable<;A<;T>&燃气轮机;如果T ;: ;IEquatable<;T>;。我如何才能做到这一点,并保持IEnumerable以及?,c#,inheritance,interface,C#,Inheritance,Interface,我有一个树形类Foo,它的接口是IFoo 我希望Foo能够在T:IEquatable时实现IEquatable(或者更一般地说,如果T:I我可能需要Foo:I以及其他实现的接口) 我尝试了以下代码: public interface IFoo<T> : IEnumerable<IFoo<T>> ... public class Foo<T> : IFoo<T> ... public interface IFooTwo<T&

我有一个树形类
Foo
,它的接口是
IFoo

我希望
Foo
能够在
T:IEquatable
时实现
IEquatable
(或者更一般地说,如果
T:I
我可能需要
Foo:I
以及其他实现的接口)

我尝试了以下代码:

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) { ... }
}      
公共接口IFoo:IEnumerable
...
公共类Foo:IFoo
...
公共接口IFooTwo:IFoo,IEquatable
其中T:i可满足
...
公共类FooTwo:IFooTwo{
…//我实现了Equals
公共bool-NewMethod(FooTwo-Other){…}
}      
因此,现在我成功地实现了
Equals
(我还覆盖了generic Equals,等等)

但是
FooTwo
现在不实现
IEnumerable
(而是实现
IEnumerable

所以我有两个问题:

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


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

    对于问题1,您应该考虑您是否真的需要它<代码>IEquatable。在您的情况下,不应该有任何理由需要确保您使用的是
    IEquatable
    equals,而不是object。例如,
    Tuple
    就是这样做的。然后,您可以只使用一个没有约束的界面:

    public interface IFoo<T> : IEnumerable<IFoo<T>>, IEquatable<IFoo<T>>
    
    公共接口IFoo:IEnumerable,IEquatable
    
    对于问题2,您可能也不需要这个
    IEnumerable
    是,这意味着如果您有一个
    IEnumerable
    ,您可以将其分配给类型为
    IEnumerable
    的变量,只要
    a
    可以分配给
    B
    。在您的情况下,这意味着如果您有,例如,一个采用
    IEnumerable
    的方法也将接受
    IEnumerable
    ,因为
    IFooTwo:IFoo


    但是,如果您希望将类
    MyFoo:IFoo
    的类型设置为
    IEnumerable
    ,则无法自动执行此操作。这是因为有一个有效的
    IEnumerable
    实现是完全可能的,而不是
    IEnumerable
    的实现。您可能应该将此需求视为一种设计气味,并尝试避免它。

    因为您实际上是在尝试让一些
    IFoo
    对象成为
    IEquatable
    对象,而另一些则不是,这显然与类型系统不一致,所以我会完全避免
    IEquatable
    。使用
    IEqualityComparer
    。只要提供一种方法,在给定
    IEqualityComparer
    时创建
    IEqualityComparer
    (或者使用
    T
    的默认比较器,如果需要)

    通过这样做,
    IFoo
    对象没有义务进行自我比较,但是任何人都可以创建一种方法来比较
    IFoo
    对象,只要他们知道如何比较底层对象

    这还完全消除了对
    IFoo
    的多个实现的需要,大大简化了整个代码库,并完全消除了其他问题

    如何使
    FooTwo
    实现
    IEnumerable
    使用
    Foo IEnumerable
    以快速简便的方式实现

    (如果您选择不按照我的建议更改处理平等的方式:)

    如果您知道序列中的所有项实际上都是正确的类型,那么只需对序列使用
    Cast()


    如果序列中的项目实际上不是
    FooTwo
    对象,那么您需要将项目投影到一个新序列中,在该序列中,您将每个
    IFoo
    项目映射到
    FooTwo
    项目。

    您如何确定它实现了
    IEnumerable
    而不是
    IEnumerable
    ?您是对的,编辑编辑编辑问题时请注意预览窗格,尤其是在您试图讨论泛型类型参数时。我已经修复了您的代码一次,我没有心情再为您的编辑做一次(请尝试阅读当前显示的内容,看看它有多大意义)我不知道我的编辑有什么问题,我觉得一切都很好。阅读您的问题。编辑的第一行是“在IEquatable>的特例中,我对问题1有一个简单的答案。”。你真的想说“足够”>?不,您的意思是在那里有一个通用参数。但是,因为您没有将该部分标记为代码,所以它被解释为HTML标记,并吞没了其中的一部分。现在,对于问题1,我可以测试T:IEquatable,并更改我的IEquatable.Equals函数的实现。但是,如果它是另一个接口而不是IEquatable呢?但对于问题2,我不能将我的FooTwo类列举为我想做的FooTwo。(例如,
    foreach(FooTwo t in x)
    将因x
    FooTwo
    @celestinsint-Loup而失败。您可以始终在
    FooTwo
    的声明中添加“:IEnumerable”。显然,如果
    x
    (在您的示例中)具有静态类型
    IFooTwo
    ,而不是
    FooTwo
    ,这是不可能的