2015-06-23 16 views
34
class ResultBase {} 
class Result : ResultBase {} 

Task<ResultBase> GetResult() { 
    return Task.FromResult(new Result()); 
} 

Trình biên dịch bảo tôi rằng nó không thể chuyển đổi hoàn toàn Task<Result> thành Task<ResultBase>. Ai đó có thể giải thích tại sao điều này? Tôi đã có thể mong đợi đồng phương sai để cho phép tôi viết mã theo cách này.Tại sao Task <T> không cùng biến thể?

+2

Infterfaces chỉ có thể là covariant hoặc contravariant. Lớp luôn luôn là bất biến. Đọc thêm về: http://stackoverflow.com/questions/13107071/why-classes-that-implement-variant-interfaces-remain-invariant –

+0

Các lớp là bất biến trong C#. – Lee

+3

Từ [câu trả lời này] (http://stackoverflow.com/questions/12204755/can-should-tasktresult-be-wrapped-in-ac-sharp-5-0-awaitable-which-is-covarian) dường như ai đó đã viết [một itask wrapper] (https://github.com/jam40jeff/ITask) cho nó. Ngoài ra người ta có thể bỏ phiếu cho [một đề nghị để thực hiện nó ở đây] (https://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/5754247-make-task-t-implement-covariant-interface-itask- o). –

Trả lời

17

Theo someone who may be in the know ...

Các biện minh được rằng lợi thế của hiệp phương sai là nặng hơn bởi những bất lợi của sự lộn xộn (tức là tất cả mọi người sẽ phải đưa ra quyết định về việc liệu sử dụng Task hoặc ITask trong mỗi đơn nơi trong mã của họ).

Nghe có vẻ như tôi không có động lực hấp dẫn nào cả. ITask<out T> sẽ đòi hỏi rất nhiều tình trạng quá tải mới, có thể hơi dưới mui xe (tôi không thể chứng thực lớp cơ sở thực tế được thực hiện như thế nào hoặc nó đặc biệt như thế nào so với thực hiện ngây thơ) nhưng cách khác ở dạng linq giống như này phương pháp mở rộng.

Một người nào đó đã tạo ra một điểm tốt - thời gian sẽ tốt hơn là dành class es covariant và contravariant. Tôi không biết nó sẽ khó như thế nào, nhưng điều đó nghe có vẻ như là thời gian tốt hơn với tôi.

Mặt khác, ai đó đã đề cập rằng sẽ rất tuyệt khi có một tính năng như yield return thực có sẵn trong phương thức async. Ý tôi là, không có bàn tay.

+5

'async',' await' dựa vào sự tồn tại của một phương thức 'GetAwaiter' phù hợp để nó đã được tách ra khỏi lớp' Task'. – Lee

+0

Tôi đã chỉnh sửa/chỉnh sửa –

6

Tôi nhận ra tôi là muộn để đảng, nhưng đây là một phương pháp mở rộng Tôi đã sử dụng để giải thích cho tính năng này mất tích:

/// <summary> 
/// Casts the result type of the input task as if it were covariant 
/// </summary> 
/// <typeparam name="T">The original result type of the task</typeparam> 
/// <typeparam name="TResult">The covariant type to return</typeparam> 
/// <param name="task">The target task to cast</param> 
[MethodImpl(MethodImplOptions.AggressiveInlining)] 
public static Task<TResult> AsTask<T, TResult>(this Task<T> task) 
    where T : TResult 
    where TResult : class 
{ 
    return task.ContinueWith(t => t.Result as TResult); 
} 

Bằng cách này bạn có thể chỉ cần làm:

class ResultBase {} 
class Result : ResultBase {} 

Task<ResultBase> GetResult() 
{ 
    return Task.FromResult(new Result()).AsTask<Result, ResultBase>(); 
} 
Các vấn đề liên quan