3

ジェネリック カード クラスから継承し、所有するデッキへの参照をすべて含む、さまざまなタイプのカードの表現を作成しようとしています。

ここで提案されているように、それらを再宣言しようとしましたが、それでも特定のカード タイプに変換されません。

私が現在持っているコードは次のとおりです。

public class Deck<T> : List<T> 
    where T : Card 
{
    void Shuffle()
    {
        throw new NotImplementedException("Shuffle not yet implemented.");
    }
}

public class Card
{
    public Deck<Card> OwningDeck { get; set; }
}

public class FooCard : Card
{
    public Deck<FooCard> OwningDeck
    {
        get
        {
            return (Deck<FooCard>)base.OwningDeck;
        }
        set
        {
            OwningDeck = value;
        }
    }
}

私が得ているコンパイル時エラー: Error 2 Cannot convert type Game.Cards.Deck<Game.Cards.Card>toGame.Cards.Deck<Game.Cards.FooCard>

そして、新しい演算子を使用して非表示が意図的であることを指定することを示唆する警告。そうすることは慣習に違反しますか?より良い方法はありますか?

stackoverflow に対する私の質問は次のとおりです。私がしようとしていることは、.NET 型システムでエレガントに実行できますか? もしそうなら、いくつかの例を提供できますか?

4

3 に答える 3

3

使用しているカードの基本クラスを指定する汎用パラメーターをカードに装備できます。

public class Card<TCard>
    where TCard : Card<TCard>
{
    public Deck<TCard> OwningDeck { get; set; }
}

クラスFooCardは次のようになります。

public class FooCard : Card<FooCard>

OwningDeck現在のコードに対する利点は、プロパティを再宣言する必要がないことです。自動的に in 型Deck<FooCard>になりFooCardます。

于 2012-09-23T21:41:23.130 に答える
2

ここでヒットしているのは、「OwningDeck」の基本宣言を「隠している」プロパティ「OwningDeck」を FooCard に特化しようとしているという、一般的な設計ミスです。'OwningDeck' を Card クラスに入れるという選択は、すべてのタイプの Card が OwningDeck プロパティを持つことを保証することを目的としています。 ')。

そのため、派生型 (FooCard など) でこのプロパティを再宣言することはできません。これは、プロパティの型を変更しようとしているためです (設計上の選択としては不適切です)。実際には .net でサポートされていません。

警告が表示される理由は、プロパティがプロパティをDeck<FooCard> OwningDeck非表示にするためですDeck<Card> OwningDeck。誰かが変数を typeCardにキャストしてからプロパティにアクセスするOwningDeckと、OwningDeck からプロパティを取得します。ただし、それをキャストしてFooCard同じプロパティにアクセスすると、から返された値が取得されDeck<FooCard> OwningDeckます。コンパイラーは、これらが同じ変数にアクセスしている可能性があることを知りませんが、プログラマーはコードからこの動作を予期しないため、非常に危険です。

より良い実装に関しては、 OR Mapperが実際の実装に勝っています。彼が言った事 ;)

于 2012-09-23T21:43:21.810 に答える
2

Card次のように、クラスをジェネリックにしたい場合は、探しているものに近いものを実現できます。

public class Deck<T> : List<Card<T>> 
    where T : Card<T>
{
    void Shuffle()
    {
        throw new NotImplementedException("Shuffle not yet implemented.");
    }
}

public class Card<T> where T : Card<T>
{
    public Deck<T> OwningDeck { get; set; }
}

public class FooCard : Card<FooCard>
{
}

元のコードが機能しない理由は、 aDeck<Card>が a と同じでなく、Deck<FooCard>その逆でもないからです。次のことを想像してください。

Deck<Card> deck = new Deck<Card>();
deck.Add(new BarCard());
Deck<FooCard> fooDeck = (Deck<FooCard>)deck;  // What should happen here?
FooCard foo = deck[0];                        // or here?

ですから、「なぜCardクラスはどのデッキを所有しているかを気にするのですか?」と自問する必要があります。私が知っているほとんどのプログラムでは、カードがその詳細を認識する理由はありません。その について何かを知りたい特定の理由がある場合、それについてDeck実際にどれだけ知る必要があるのDeckでしょうか? たとえば、デッキにさまざまなDeck種類のカードを入れることは可能ですか? デッキからカードを取り出すとき、それらが現在のカードとまったく同じタイプのカードになることを本当に知る必要がありますか?

これらのような質問に答えたら、実装する共変または反変のインターフェイスであるOwningDeck必要があるかどうか、またはそれがクラスに属しているかどうかを判断する準備が整います。Deck<T>Deck<T>Card

于 2012-09-23T21:45:15.350 に答える