3

ここで私のビジョンを説明するために最善を尽くします。これは非常に不完全な作り上げの例です。私はいくつかの異なるタイプを持ってBagいます、そしてそれらはすべて彼ら自身の特別なタイプを持っていMarbleます。の各タイプにMarbleは、独自のニックネームのセット(strings)があります。

残念ながら、Marble in the Bag以外にも他のものがあるので、ジェネリックはここでは役に立ちません。

// Bags
abstract class Bag {
    protected Type MarbleType { get; }
    protected List<Marble> _marbles;

    public void DumpBag()
    { ... }
}
class RedBag : Bag {
    override Type MarbleType { get { return typeof(RedMarble); } }
}
class BlueBag : Bag {
    override Type MarbleType { get { return typeof(BlueMarble); } }
}

// Marbles
abstract class Marble {
    public static IEnumerable<string> Nicknames {
        get {
            return new List<string>() {
               "Marble", "RollyThing"
            }
        }
    }
}
class RedMarble : Marble {
    public static IEnumerable<string> Nicknames {
        get {
            return new List<string>(Marble.Nicknames) {
                "Ruby"
            };
        }
    }
}
class BlueMarble : Marble { ... }

さて、詳細、の実装について説明しDumpBag()ます。次の呼び出しについて考えてみます。

Bag b = new RedBag();
b.GetMarbles();
b.DumpBag();

印刷したい:

Bag of Marbles (aka "Marble", "RollyThing", Ruby"):
- Marble 1
- Marble 2
...

その見出しを印刷するには、実際のインスタンスに関係なく、Bag派生したタイプの知識を持っている必要があることがわかります。基本クラスのの連結だけでなく、派生したもMarble取得します。NicknamesMarbleRedMarble

DumpBag一種の「静的仮想呼び出し」を行う必要があります。私はDumpBag以下から実装を開始しました:

public void DumpBag() {
    PropertyInfo pi = this.MarbleType.GetProperty("Nicknames", BindingFlags.Static);
    IEnumerable<string> nicknames = pi.GetValue(null, null);  // No instance

    StringBuilder sb = new StringBuilder("Bag of Marbles (aka ");
    foreach (string nn in nicknames)
        sb.Append("\"" + nn + "\", ");
    Console.WriteLine(sb.ToString());

    ...
}

私の質問:

  1. これは正気ですか?うまくいけば、私がこのルートを選んだ理由を説明することができます(またはできる)。
  2. RedMarble.Nicknames(もちろん)非表示の警告が表示されMarble.Nicknamesます。先に進んでマークを付けることは有効だと思われますnewか?
4

1 に答える 1

3

足りないのは明示的なキャストだけです。

(List<string>)this.MarbleType.GetProperty("Nicknames").GetValue(null, null);

私がそれをテストしたとき、これは私にとってうまくいきました。

コメントで説明されているように、実際にはnewキーワードを使用するべきではありません。あいまいさがないように、基本クラスの静的メソッドに別の名前を付けることをお勧めします。結局のところ、あなたはこれを管理していて、他の誰かのコードを使用していません。


さて、あなたはそれをこのようにすべきですか?

まず、型を返すために、定義されていないジェネリックメソッドを使用する必要があります。

abstract class Bag<T> where T:marble {
    public void DumpBag()
    { 
        // here you can use
        // (IEnumerable<string>)typeof(T).GetProperty("Nicknames").GetValue(null, null);
    }
}

class RedBag : Bag<RedMarble> {
}

class BlueBag : Bag<BlueMarble> {
}

もちろん、2番目にできることは、これを静的ではないようにすることです。この場合、プロパティはで抽象化されMarble、でオーバーライドされRedMarble、リフレクションを使用せずに直接BlueMarbleアクセスされます。DumpBagNicknames

于 2012-05-01T20:43:16.387 に答える