2

実装クラスのインターフェイス プロパティにアクセスしようとすると、問題が発生します。問題は、実行時に特定の (Cat) タイプしか持っていないため、キャストしようとするとアプリが壊れてしまうことです。

ここに私が持っているものがあります:

public class Animal {}
public class Cat : Animal {}

public interface IPetSitter {}
public interface IPetSitter<T> IPetSitter where T : Animal {
    T Pet { get; set; }
}

public class Kid { }

public class NeighborhoodKid : Kid, IPetSitter<Animal> {
    Animal Pet { get; set; }
}

// --- Implementation ---

// Kid Timmy is instantiated elsewhere
// Animal type "A" is passed in dynamically

if (Timmy is IPetSitter) {
    ((IPetSitter<A>)Timmy).Pet = new A();
}

タイプが一致しない場合、このキャストはエラーになります。私はこのようなことをしたいと思います:

public interface IPetSitter {
    object Pet { get; set; }
}

public interface IPetSitter<T> : IPetSitter where T : Animal {
    new T Pet { get; set; }
}

// --- Implementation ---

NeighborhoodKid Timmy = new NeighborhoodKid();
((IPetSitter)Timmy).Pet = new Cat();

しかし、これにより、IPetSitter を実装するものはすべて [object Pet] プロパティと [Cat Pet] プロパティの両方を持つようになります。

アイデアをいただければ幸いです。ありがとう。

更新:最初はもっと明確にするべきでしたが、クラスを作成することもあれば、Kidクラスを作成することもありNeighborhoodKidます。そのため、にキャストする必要がありIPetSitter<T>ます。私が作成するすべての子供が座っているペットになるわけではありません。これは不気味に聞こえ始めています。

4

4 に答える 4

0

ティミーは、最終的に、NeighborhoodKidとして初期化されました。つまり、彼にとって、ペットは動物です。ティミーはですIPetSitter<Animal>、そしてあなたはそれをにキャストすることはできませんIPetSitter<Cat>

ただし、Cat:Animalを想定すると、逆の方法で行うこともできます。

これ:

((IPetSitter<Animal>)Timmy).Pet = new Cat();

IPetSitter<Animal>NeighborhoodKid:なので、Timmyが実際に機能しているという理由だけで実際に機能IPetSitter<Animal>します。したがって、そのキャストでは実際には何もしていません。ペットのプロパティにアクセスするだけです。

その後の回線の問題は、Petにアクセスしたり、Catを入れたりすることではなく、TimmyをキャストするIPetSitter<Cat>ことです。あなたはそれをそうではない何かにダウンキャストしています。

いつでもアップキャストできますが、オブジェクトを初期化したものにのみダウンキャストできます。

NeighborhoodKidを動物自体を含むあらゆる種類の動物のIPetSitterにしたい場合は、次のことを行う必要があります。

public class NeighborhoodKid<T> : IPetSitter<T> where T : Animal
{
    ...
}

このように、それは一般的であり、直接的または間接的を問わず、動物または動物から派生したもののいずれかであることに制約します。

それでも、として初期化した場合、 (NeighborhoodKidコンストラクターに指定された汎用TパラメーターがAnimalであり、に渡されるため)として初期化されたため、new NeighborhoodKid<Animal>()(別名キャスト先)として表示することはできません。 IPetSitter汎用パラメーター)。IPetSitter<Cat>IPetSitter<Animal>

于 2012-05-08T17:05:56.180 に答える
0

コレクションでの有用性以外では、私はジェネリックのファンではありません。これが理由です。すべての NeighborhoodKid を 1 つの特定の種類の Animal にバインドするように強制しています。ティミーが猫や犬を観察できるとしたら? それぞれに異なる Timmy インスタンスを作成しますか?

代わりに、インスタンスレベルで動物の種類を強制していると思います。例(簡潔にするために一部のタイプを切り捨てました):

public interface IAnimal {...}

public class Cat : IAnimal {...}

public interface IPetSitter
{
    IAnimal Pet { get; set; }
}

public class Kid : IPetSitter
{
    public Kid (params Type[] allowedPets) {
        _allowedPets = allowedPets;
    }

    readonly IEnumerable<Type> _allowedPets;

    IAnimal _pet;
    public IAnimal Pet 
    {
        get {
            return _pet;
        }
        set {
            if (!_allowedPets.Contains(value.GetType()) {
                throw new InvalidArgumentException("This instance does not support " + value.GetType().Name + ".");
            }
            _pet = value;
        }
    }
}

強制をインスタンス レベルのままにしておくと、プロパティを設定するためだけに具体的なキャストを使用する必要は必ずしもありません。

于 2012-05-08T21:29:31.143 に答える
0

だけではないのはなぜTimmy.Pet = new Cat();ですか?それを作るだけでpublic準備完了です:

public class NeighborhoodKid : Kid, IPetSitter<Animal>
{
   public Animal Pet { get; set; }
}

から継承しない NeighborhoodKid を作成するIPetSitterと、セッターは利用できません。

public class LazyNeighborhoodKid : Kid
{
   // Nothing here, hes not a Pet Sitter, can access Pet
}
于 2012-05-08T17:25:47.907 に答える
0

問題は、あなたが定義したことです

public class NeighborhoodKid : IPetSitter<Animal>
{
    Animal IPetSitter<Animal>.Pet { get; set; }
}

そしてそうではない

public class NeighborhoodKid : IPetSitter<Cat>
{
    Cat IPetSitter<Animal>.Pet { get; set; }
}

また

public class NeighborhoodKid<T> : IPetSitter<T> where T : Animal
{
    Cat IPetSitter<T>.Pet { get; set; }
}
于 2012-05-08T17:08:39.180 に答える