2012-07-06 45 views
8

我已經簡化並在下面的代碼中再現了我的問題。我收到的錯誤是:參數1:無法從'System.Collections.ObjectModel.Collection'轉換爲'System.Collections.ObjectModel.CollectionC#將一個集合作爲一組接口傳遞

導致此問題的設計決策的一些背景:我有創建了一個用於處理「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); 
} 

回答

9

試着改變你的EatFruit方法,因爲它標有out修改接受IEnumerable<IFruit>

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

接口IEnumerable<out T>支持協方差。 Collection<T>沒有標註這樣的修飾符。

+0

謝謝。這編譯。現在更新我的單元測試。 – YouGotCSharpInMyJava 2012-07-06 18:08:36

1

這就是所謂的協方差。
但是,這是不可能的可變集合。

否則,EatFruit可以寫

fruits.Add(new Orange()); 

.NET 4中不支持的協方差僅爲REAS接口,這樣你就可以把它改成IEnumerable<IFruit>,它會工作。

+0

假設Orange實現了IFruit,那麼在那裏是否存在問題? – Charleh 2012-07-06 17:59:23

+1

@Charleh:'fruits'實際上是'Collection '。它不能容納一個'橙色'。 – SLaks 2012-07-06 17:59:48

+0

我以爲水果是一個集合,它可以包含任何實現IFruit的類型? – Charleh 2012-07-06 18:01:23

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

(它是類型安全的,因爲你把它!)

+0

這將做2x工作 - 創建一個列表然後將每個添加到集合。更好做:'foreach(var x in fruit.OfType ()){col.Add(x); }'。 – 2012-07-06 19:44:48

+0

是的 - 我說它沒有任何性能(我在那裏也提到了可怕的東西!):D – Charleh 2012-07-06 19:45:21

0

簡單的解決方案:

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

更好的解決方案:使用C#4中引入的協方差:請參閱Kevin的答案

相關問題