2017-05-01 16 views
-1

以下のコードがc#(.NET Core 1.1)で動作しない理由を理解できません。C#がジェネリックスとインターフェイスに固執しました

public interface IChild 
{ 
} 

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

public abstract class ParentBase<TChild> : IParent 
    where TChild : IChild 
{ 
    public IEnumerable<TChild> Children {get; set; } 
} 

エラーメッセージが

エラーCS0738が 'ParentBase < TChild>' インターフェース部材 'IParent.Children' を実装していませんです。 'ParentBase < TChild> .Children'に一致する戻り値の型が 'IEnumerable < IChild>'ではないため、 'IParent.Children'を実装できません。

エラーメッセージは、私がIChildにTChildを制限しながら、IEnumerableを< TChild>がない< IChild> IEnumerableを型であると言います。

私はこの2つの「簡単な」方法を見つけましたが、両方ともクライアントコードにかなり悪い変更が必要です。クライアントコードでConfigurationSection.Bind()を使用して、これらのタイプのオブジェクトツリー全体をロードします。

不要な解決策1:これが動作しない理由は非常に単純です

public interface IChild 
{ 
} 

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

public abstract class ParentBas<TChild> : IParent 
    where TChild : IChild 
{ 
    public IEnumerable<IChild> Children {get; set; } 
} 
+4

なぜ一般的な 'ParentBas 'を使用していますか?あなたはそれを必要としません - 'IEnumerable 子供たちは'すでにIChildのすべての実装を受け入れていますか? – Fabio

+0

* "以下のコードがc#で機能しない理由を理解していない" * - インターフェイスとコンクリートクラスの間に矛盾が生じるため、犬の子を猫の親にinterface –

+0

ParentBasはミススペルされています.ParentBaseである必要があります。抽象的なParent基本クラスを持つ目的は、そこにParentの共通機能を実装することです。わかりやすくするために共通のコードを削除しました。 –

答えて

0

public interface Animal { } 

public interface ICage 
{ 
    IEnumerable<IAnimal> Animals { get; set; } 
} 

public class Cage<TAnimal> where Animal: Animal 
{ 
    public IEnumerable<TAnimal> { get; set; } //Illegal implementation of ICage 
} 

親インターフェイスジェネリック

public interface IChild 
{ 
} 

public interface IParent<TChild> 
    where TChild : IChild 
{ 
    IEnumerable<TChild> Children { get; set; } 
} 

public abstract class ParentBas<TChild> : IParent<TChild> 
    where TChild : IChild 
{ 
    public IEnumerable<TChild> Children {get; set; } 
} 

不要なソリューション2を作りますこれは、基本的には不要なひっくり返しなしで同じ設定です。今、何をしようとしていることはインターフェイスの法的な実装であれば何が起こるかを参照してください。

var dogCage = new Cage<Dog>(); 
dogCage.Animals = new[] { cat }; //Illegal! Why?!? 

、それは合理的なようだが、それはICage契約の目に余る違反です。これがあること、実際に合法である必要があります:あなたのコードは全くIParentの契約を満たしていない理由を

ICage dogCage = new Cage<Dog>(); 
dogCage.Animals = new[] { cat }; //Legal! 

だから、あなたは明らかに見ることができます。

+0

申し訳ありませんが、全く私にはっきりしません。 dogCageのタイプがCage の場合、両方の例でCatリストをAnimalsリストに追加するのは不正です。まだ、IParent、IChild、ParentBaseの宣言が違法である理由は分かりません。 –

+0

@StefaanVandeveldeインターフェース 'ICage'は、 'IEnumerable 'を含む 'IEnumerable 'を受け入れるので、うまくいっています。あなたの提案で 'Cage 'は 'IEnumerable 'しか認めません。それは 'ICage'の契約に違反している。 – InBetween

+0

@StefaanVandeveldeそれはポイントです。あなたのインターフェースは何も許可しません。実装するクラスのジェネリックタイプが何であれ、 'IAnimal'は有効です。なぜインタフェースは 'TAnimal'を心配すべきですか?それはそれについて何も知らない... – InBetween

関連する問題