2015-05-25 56 views
4

考慮一個類Foo,它完全實現了IFoo。 同時,考慮任務Task<IFoo>將具體任務<TImplementation>分配給類型變量任務<TInterface>

爲什麼當調用以下內容時會引發編譯錯誤;

Task<IFoo> task = Task.Factory.StartNew(() => new Foo()); 

編譯器說,它不能從源類型Task<Foo>轉換爲Task<IFoo>。雖然這是有道理的,因爲它們本質上是兩種不同的類型,是否不會與IList<IFoo> list = new List<IFoo>{new Foo(/* construct */)};或其他類似的分配屬於同一前提?

此刻我強制演員進入界面,但這種感覺並不合適。

+3

你的反例是不計。列表也不能被分配給IList 。 –

+0

嗯,你說得對。那麼我想這件事就在同一條毯子下。 –

+0

我通常從波特蘭水泥和水的混合物中回收混凝土。也許你可以編輯你的標題更具描述性。 –

回答

9

這是因爲這種說法Task.Factory.StartNew(() => new Foo());返回Task<Foo>類型的實例。

並且考慮到Task<>類是一個具體類,除非它實現協變接口(即ITask<out T>),否則它不能是協變的。

請注意,有一個uservoice話題可以做到這一點:"Make Task implement covariant interface ITask"

還要注意爲什麼事情是這樣的,現在以下可能的解釋,"Lack of Covariance in the Task Class"

框架指導方針是:

  • 如果你的框架已經包含了其他原因的接口,然後通過一切手段使它合作+逆變。
  • 但是不要僅僅爲了實現co +逆變的目的而引入接口。

的理由是,協方差的好處是雜亂的缺點抵銷(即每個人都必須做出關於是否在他們的代碼中使用Task<T>ITask<T>在每一個所決定)。

現在你要做的:

Task<IFoo> task = Task.Factory.StartNew<IFoo>(() => new Foo()); 
+0

謝謝,爲此。我真的是爲什麼而不是如何,而這又碰撞了腦袋。 –

+0

@DanielPark如果您認爲這個問題能夠充分解決您的問題,您可能希望接受它作爲答案,以便您的問題可以從「未回答的問題」列表中刪除。 – Alex

0

您可以使用通用版本

Task<IFoo> task = Task.Run<IFoo>(() => new Foo());