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
}
}