9

以下のコードで問題を単純化して再現しました。私が受け取っているエラーは次のとおりです: 引数 1: 'System.Collections.ObjectModel.Collection' から 'System.Collections.ObjectModel.Collection' に変換できません

この問題につながった設計上の決定の背景: 「IFruit」を処理するための Web サービスを作成しましたが、SOAP とエンドポイント バインディングの性質上、IFruit の明示的な実装を使用してメソッドを作成しました。ビジネス層では、果物の特定の実装ごとに個別のメソッドを作成すると、まず多くの重複コードが発生し、次に、Web サービスで新しい IFruit 型を受け入れるために後でコードを変更する必要があるほど、ビジネス層とサービス層が緊密に結合されます。ビジネス層で (冗長コードの別のコピーを追加します)。この設計は、私が過去に Java を使用して正常に実装したものですが、C# のインターフェイスは私を驚かせるほど異なっているようです。お知らせ下さい。

public interface IFruit{
    public string TakeBite();
}

public Apple : IFruit{
    public string TakeBite(){
        return "tasty bite of apple";
    }
}

public void EatFruit(Collection<IFruit> fruits){
    foreach(var fruit in fruits){
        Console.WriteLine(fruit.TakeBite());
    }
}

public void EatApples(Collection<Apple> apples){
    this.EatFruit(apples);
}
4

4 に答える 4

10

EatFruit受け入れ方法を変更してみてくださいIEnumerable<IFruit>

public void EatFruit(IEnumerable<IFruit> fruits)
{
    foreach (var fruit in fruits)
    {
        Console.WriteLine(fruit.TakeBite());
    }
}

インターフェイスは修飾子 IEnumerable<out T>でマークされているため、共分散をサポートします。はそのような修飾子でマークされていません。outCollection<T>

于 2012-07-06T18:00:04.930 に答える
1

それは共分散と呼ばれます。
ただし、可変コレクションでは不可能です。

そうでなければ、EatFruit書くことができます

fruits.Add(new Orange());

.Net 4 は、reas-only インターフェイスの共分散をサポートしているため、変更して機能させることができますIEnumerable<IFruit>

于 2012-07-06T17:58:06.310 に答える
1

簡単な解決策:

public void EatApples(Collection<Apple> apples){
     this.EatFruit(
          new Collection<IFruit>(
              apples.Cast<IFruit>()
          )
     );
}

より良い解決策: C# 4 で導入された共分散を使用します: Kevinの回答を参照してください

于 2012-07-06T18:16:56.077 に答える
0

IEnumerable を使用する以外に、コレクションをタイプ チェックできます (少し恐ろしいですが、動作するはずです)。

public void EatApples(Collection<IFruit> fruit)
    var col = new Collection<IFruit>();

    fruit.Where(x => x is Apple).ToList().ForEach(x => col.Add(x));

    this.EatFruit(col);
}

代わりに IEnumerable を使用しますが、これはリファクタリングできない場合の単なるオプションです:P

(あなたが作るのと同じくらい型安全です!)

于 2012-07-06T18:09:59.700 に答える