1

次のことを考慮してください。

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

アイデアは、いくつかのタイプのツリーを実装することです。ただし、この方法は、同じタイプUnion()の2つのツリーを結合しようとした場合にのみ機能します。ただし、上記の型アノテーションはこの制限を強制しません。

だから、私の質問は次のとおりです。引数がと同じ型でなければならないUnion()ような型署名をどのように書くことができますか?otherthis

(明らかに、動的ランタイムテストを実行し、型が一致しない場合は例外をスローすることができます。しかし、実行できる場合は、コンパイル時にこれをチェックすることをお勧めします...)

4

4 に答える 4

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)
    {
    }
}
于 2013-03-14T19:27:32.617 に答える
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
        }
    }
    
于 2013-03-14T21:21:19.683 に答える
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>必要に応じて他のメソッドを使用することもできます。

于 2013-03-14T19:27:25.487 に答える
0

どういうわけか、以下は実際にコンパイルされます:

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# ジェネリックでは、ジェネリック型を具体化するために、ある時点でジェネリック型パラメーターの値を認識している必要があります。

于 2013-03-14T19:30:05.623 に答える