C# 参数类型与该类匹配

C# 参数类型与该类匹配,c#,types,C#,Types,考虑以下几点: public interface ITree<X> { ... ITree<X> Union(ITree<X> other); ... } 公共接口ITree { ... ITree联盟(ITree其他); ... } 我的想法是要实现几种类型的树。但是,Union()方法仅在尝试合并相同类型的两棵树时有效。但是,上面的类型签名不强制执行此限制 因此,我的问题是:如何为Union()编写一个类型签名,使得other参数必须具有与

考虑以下几点:

public interface ITree<X>
{
  ...
  ITree<X> Union(ITree<X> other);
  ...
}
公共接口ITree
{
...
ITree联盟(ITree其他);
...
}
我的想法是要实现几种类型的树。但是,
Union()
方法仅在尝试合并相同类型的两棵树时有效。但是,上面的类型签名不强制执行此限制

因此,我的问题是:如何为
Union()
编写一个类型签名,使得
other
参数必须具有与
this
相同的类型


(显然,我可以做一个动态运行时测试,如果类型不匹配,我会抛出一个异常。但是如果可以的话,我更愿意在编译时检查它…)

那么为什么需要这个接口呢?只需在树的每个实现上实现一个
Replace
方法:

public class RedBlackTree<T> {
    public RedBlackTree<T> Union(RedBlackTree<T> other) { ... }
}

public class SplayTree<T> {
    public SplayTree<T> Union(SplayTree<T> other) { ... }
}
公共类RedBlackTree{
公共红黑树联盟(红黑树其他){…}
}
公共类八字树{
公共八字树联盟(八字树其他){…}
}

由于您在处理
ITree
的每个实现时都在寻找编译时安全性,因此我认为您只需要处理具体类型。当然,如果需要,您可以使用带有其他方法的
ITree

没有一种特别干净的方式来表达这一点,这是使用接口的结果,因为无法知道
ITree
的实现类型。最好的方法可能是创建另一个类/接口,该类/接口约束具体的树类型,并执行所需的操作:

public interface ITreeUnion<T, X> where T : ITree<X>
{
    T Union(T left, T right);
}
不知何故,以下几点:

公共接口ITree其中TSelf:ITree
{
自我联盟(自我-其他);
// ...
}
公共类AvlTree:ITree{
公共AvlTree联盟(AvlTree其他){
归还他人;
}
}

当然,它不是特别有用,因为那时您必须将变量声明为
ITree
,此时您最好不要使用接口。对于C#泛型,泛型类型参数的值必须在某个时刻已知,才能具体化泛型类型。

根据您的要求,您需要一个
Union()的泛型声明

  • 接口

    public partial interface ITree<X> {
        T Union<T>(T other) where T: ITree<X>;
    }
    

@JLRishe-它不会被强制执行,因为如果它们都实现了
ITree
,那么你可以将
RedBlackTree
SplayTree
合并!你说得对。我以为问题是指
X
@Lee,我不确定泛型系统是否可以用任何有用的方式表示类型约束。(不仅仅是界面中没有这些方法。)我曾经尝试过编写诸如
T
之类的术语,但编译器不喜欢。我没有想过尝试使用
t:ITree
约束;那真是太巧妙了!与此相关,显然可以将
Union
作为一种“扩展方法”,使其看起来不那么奇怪。(虽然这本身并没有提供我想要的动态绑定。)哦,这很有趣。。。我不知道重写方法会给泛型参数添加新的类型约束。您不是重写方法,而是实现接口。泛型方法定义无论定义在何处,编译器甚至会在您使用与类定义相同的类型参数声明时发出警告。
public interface ITree<TSelf, TItem> where TSelf : ITree<TSelf, TItem>
{
    TSelf Union(TSelf other);
    // ...
}

public class AvlTree<TItem> : ITree<AvlTree<TItem>, TItem> {
    public AvlTree<TItem> Union(AvlTree<TItem> other) {
        return other;
    }
}
public partial interface ITree<X> {
    T Union<T>(T other) where T: ITree<X>;
}
public partial class TreeOfObject: ITree<object> {
    public T Union<T>(T other) where T: ITree<object> {
        return default(T); // sample only; shuold be implemented yourself
    }
}

public partial class TreeOfInt: ITree<int> {
    public T Union<T>(T other) where T: ITree<int> {
        return default(T); // sample only; shuold be implemented yourself
    }
}
public static partial class TestClass {
    public static void TestMethod() {
        var x=new TreeOfObject();
        var y=new TreeOfInt();

        var xx=x.Union(x);
        var yy=y.Union(y);

        var xy=x.Union(y); // won't compile
        var yx=y.Union(x); // won't compile
    }
}