2013-03-14 67 views
1

考虑下面的比赛:参数类型该类

public interface ITree<X> 
{ 
    ... 
    ITree<X> Union(ITree<X> other); 
    ... 
} 

的想法是,我要实现几种类型的树。但是,Union()方法仅适用于如果您尝试将的两棵树组合在一起的。但是,上面的类型签名不会强制执行此限制。

所以,我的问题是:我如何写一个类型签名Union()使得other参数必须具有同一类型this? (显然,如果类型不匹配,我可以做一个动态运行时测试并抛出一个异常,但是如果可以完成的话,我会在编译时检查它)。

+2

@JLRishe - 这不会是因为如果他们都执行“ITree ”,您可以将“RedBlackTree ”与“SplayTree ”联合起来。 – Lee 2013-03-14 19:20:54

+0

爆炸!你是对的。我认为这个问题是指“X”。 – JLRishe 2013-03-14 19:23:05

+0

@Lee我不确定这是泛型系统可以用任何有用的方式表达的类型约束。 (只是没有在界面中的方法。) – millimoose 2013-03-14 19:24:12

回答

2

表达这一点并不是一种特别干净的方式,这是使用接口的结果,因为没有办法知道ITree<X>的实现类型。最好的方法可能是创建另一个类/接口,限制了混凝土树类型并执行操作()你需要:

public interface ITreeUnion<T, X> where T : ITree<X> 
{ 
    T Union(T left, T right); 
} 

你那么有这个接口类型的实例传递给你需要的地方进行所需的操作。

如果你真的需要Union去,你可以使用一个循环模板的接口上:

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

public class RedBlackTree<T> : ITree<RedBlackTree<T>, T> 
{ 
    public RedBlackTree<T> Union(RedBlackTree<T> other) 
    { 
    } 
} 
+0

我曾尝试写'T '等术语,但编译器不喜欢它。我没有想过试图使用'T:ITree '约束;这很巧妙! – MathematicalOrchid 2013-03-14 19:54:34

+0

与此相关的是,你显然可以将'Union'作为一种“扩展方法”,使它看起来不那么奇怪。 (虽然这本身并不给我想要的动态绑定。) – MathematicalOrchid 2013-03-21 08:18:55

0

为什么你需要界面呢?简单地实现对树的每个实施Replace方法:

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

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

既然你用的ITree每个执行交易时寻找编译时的安全性,我认为你只需要处理的具体类型。当然,如果需要,您可以使用其他方法ITree<T>

0

不知何故,以下actually compiles

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

当然,这不是特别有用,因为再你必须声明变量为ITree<AvlTree>,此时你可能不会使用该接口。使用C#泛型时,通用类型参数的值必须在某个时刻已知,才能确定泛型类型。

1

根据您的需求,您需要一个Union()的通用声明。

  • 接口

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

Ooo,这很有趣......我不知道一个方法的重写可以将新的类型约束添加到通用参数。 – MathematicalOrchid 2013-03-14 22:49:10

+0

您不是覆盖方法,而是实现接口。无论在何处定义类型,通用方法定义都是无论如何,如果使用与类定义相同的类型参数声明,编译器甚至会警告您。 – 2013-03-14 22:59:21