9

次のエラーが発生します。

ClassName.PropertyNameは、IBasePropertyTypeの一致する戻りタイプがないため、IClassType.PropertyNameを実装できません。

さて、コードについて:

public class ClassName : IClassType
{
    public IChildPropertyType PropertyName { get; set; }
}

public interface IClassType
{
    public IBasePropertyType PropertyName { get; set; }
}

public interface IBasePropertyType
{
    // some methods
}

public interface IChildPropertyType : IBasePropertyType
{
    // some methods
}

私が試みていることを行う方法はありますか?問題が共変性/反変性にあることは知っていますが、これを行う方法がわからないようです。

4

2 に答える 2

8

特定のインターフェイスを実装するには、同じ戻り値の型が必要です。ただし、生活を楽にするための潜在的な回避策がいくつかあります。

  1. インターフェイスをジェネリックにする
  2. インターフェイスを明示的に実装します。

ジェネリックにするIClassTypeと、次のようになります。

public interface IClassType<T> where T : IBasePropertyType
{
    public T PropertyName { get; set; }
}

...その後、さまざまなプロパティ タイプを使用してこのインターフェイスを実装できます。

public class ClassName : IClassType<IChildPropertyType>
{
    public IChildPropertyType PropertyName { get; set; }
}

別のオプションは、インターフェイスを非ジェネリックのままにし、インターフェイスを明示的に実装するジェネリック基本型を使用することです。

public class ClassBase<T> : IClassType
    where T : IChildPropertyType
{
    IBasePropertyType IClassType.PropertyName { 
        get {return PropertyName;}
        set {PropertyName = (IChildPropertyType)value;}
    }
    T PropertyName {get;set;}
}

この最後のオプションは、プロパティを特定の子型に動的にキャストする必要があるため、あまり理想的ではないことに注意してください。すべての IChildProperty 型が IBasePropertyType であることは保証できますが、すべての IBasePropertyType が IChildPropertyType であることは保証できません。ただし、元のインターフェイスからセッターを削除できる場合、またはコード内でセッターが間違った型で呼び出されないことを保証する他の手順を実行できる場合、これは機能する可能性があります。

于 2011-02-03T17:13:49.813 に答える
6

これは共分散に関係していることは間違いありません。具体的には、仮想メソッドの戻り値の型 covarianceに関係しています。これは、C# 言語がサポートする種類の共分散ではありません。

たとえそうであったとしても、あなたが記述したシステムはタイプセーフではないことに注意してください。次があるとします。

interface IAnimal {}
interface IGiraffe : IAnimal {}
interface ITiger: IAnimal {}
class Tiger : ITiger {}
interface IHaveAnAnimal { IAnimal Animal { get; set; } }
class C : IHaveAnAnimal
{
    public IGiraffe Animal { get; set; }
}
...
IHaveAnAnimal x = new C();
x.Animal = new Tiger(); // Uh oh. We just put a Tiger into a property of type IGiraffe.

共分散がまったく正当であったとしても、この種の共分散は正当ではありません。共分散が合法であるためには、セッターが必要ありません。

次に、セッターがなかったとします。

interface IAnimal {}
interface IGiraffe : IAnimal {}
interface ITiger: IAnimal {}
class Tiger : ITiger {}
interface IHaveAnAnimal { IAnimal Animal { get; } }
class C : IHaveAnAnimal
{
    public IGiraffe Animal { get; }
}

残念ながら、これはまだ合法ではありません。しかし、これを行うことができます:

class C : IHaveAnAnimal
{
    IAnimal IHaveAnAnimal.Animal { get { return this.Animal; } }
    public IGiraffe Animal { get; }
}

C を C として使用すると、Animal はキリンを返し、IHaveAnAnimal を使用すると IAnimal を返します。

于 2011-02-03T18:03:31.170 に答える