6

Entity Framework 4 を使用してエンティティとして実装するいくつかのインターフェイスを指定しました。

public class ConcreteContainer : IContainer
{
    public EntityCollection<ConcreteChild> Children { get; set; }           
}
public class ConcreteChild : IChild
{
}
public interface IContainer
{
    IEnumerable<IChild> Children { get; set; }
}
public interface IChild
{        
}

上記から次のコンパイラ エラーが表示されます。

「Demo.ConcreteContainer」はインターフェイス メンバー「Demo.IContainer.Children」を実装していません。「Demo.ConcreteContainer.Children」は「Demo.IContainer.Children」を実装できません。「System.Collections.Generic.IEnumerable」の一致する戻り値の型がないためです。

私の現在の理解では、これはIEnumerable(EntityCollectionによって実装されています)が共変ですが、おそらく反変ではないためです。

この型パラメーターは共変です。つまり、指定した型またはより派生した型のいずれかを使用できます。共分散と反分散の詳細については、ジェネリックにおける共分散と反分散を参照してください。

私は正しいですか、もしそうなら、IContainer具象クラスを使用するのではなく、純粋に他のインターフェースに関してインターフェースを指定するという私の目標を達成する方法はありますか?

それとも、もっと根本的なことを誤解していますか?

4

3 に答える 3

5

.NET 4 の一般的な違いは、ここでは関係ありません。インターフェイスの実装は、型に関してインターフェイス シグネチャと正確に一致する必要があります。

たとえば、ICloneable次のようになります。

public interface ICloneable
{
    object Clone();
}

次のように実装できるとよいでしょう。

public class Banana : ICloneable
{
    public Banana Clone() // Fails: this doesn't implement the interface
    {
        ...
    }
}

...しかし、.NET はこれを許可しません。次のように、明示的なインターフェイス実装を使用して、これを回避できる場合があります。

public class Banana : ICloneable
{
    public Banana Clone()
    {
        ...
    }

    object ICloneable.Clone()
    {
        return Clone(); // Delegate to the more strongly-typed method
    }
}

ただし、あなたの場合、それを行うことはできません。ConcreteContainerを実装すると見なされた場合に有効な次のコードを検討してIContainerください。

IContainer foo = new ConcreteContainer();
foo.Children = new List<IChild>();

これで、プロパティ セッターは実際には でのみ動作するように宣言されているため、インターフェイスに違反して動作することEntityCollection<ConcreteChild>は明らかにありません。 IEnumerable<IChild>

于 2010-08-22T13:30:00.457 に答える
4

私の知る限り、インターフェイスを実装する必要があります。共変/反変メンバーが代わりに選択されるとは想定できません。許容されたとしても、子供向けのセッターは問題であることに注意してください。EntityCollection<ConcreteChild>またはのような他のタイプの値を持つタイプのプロパティを設定できるため、List<ConcreteChild>またはEntityCollection<ConcreteChild2>両方が実装されているためIEnumerable<IChild>です。

現在の設計では、ConcreteContainer に IContainer をプライベートに実装し、互換性のある型について IEnumerable.Children セッターの入力値を確認します。この設計にアプローチするもう 1 つの方法は、次のような汎用インターフェイスを使用することです。

public interface IContainer<T> where T:IChild
{
    IEnumerable<T> Children { get; set; }
}
于 2010-08-18T06:36:25.830 に答える
0

したがって、このインターフェイスを実装する必要がありますよね?

public interface IContainer
{
    IEnumerable<IChild> Children { get; set; }
}

ただし、実際のクラスでは、プロパティをタイプにする必要がありますEntityCollection<ConcreteChild>。これを行う方法は次のとおりです。

public class ConcreteContainer : IContainer
{
    // This is the property that will be seen by code that accesses
    // this instance through a variable of this type (ConcreteContainer)
    public EntityCollection<ConcreteChild> Children { get; set; }           

    // This is the property that will be used by code that accesses
    // this instance through a variable of the type IContainer
    IEnumerable<ConcreteChild> IContainer.Children {
        get { return Children; }
        set {
            var newCollection = new EntityCollection<ConcreteChild>();
            foreach (var item in value)
                newCollection.Add(item);
            Children = newCollection;
        }
    }
}
于 2010-08-23T01:03:01.910 に答える