2012-08-30 17 views
11

Tôi thực sự thích làm việc với lập trình C# 5.0 không đồng bộ. Tuy nhiên, có một vài nơi mà việc cập nhật mã cũ để phù hợp với mô hình TAP đang gây ra vấn đề cho tôi.Có thể/nên Task <TResult> được bọc trong C# 5.0 awaitable đó là covariant trong TResult?

Dưới đây là một trong số họ - Tôi không chắc chắn chính xác lý do tại sao Task<TResult> không hiệp biến trong TResult, nhưng nó gây khó khăn cho tôi khi cố gắng cập nhật một giao diện hiệp biến để di chuyển từ một đồng bộ để một mô hình không đồng bộ:

cũ mã:

public interface IInitializable<out T> // ** out generic modifier ** 
{ 
    /// <summary> 
    /// Boolean to indicate if class is ready 
    /// </summary> 
    bool IsInitialized { get; } 

    /// <summary> 
    /// Calls for instance to be initialized using current parameters 
    /// Driver initialization can be done in the default constructor if desired 
    /// </summary> 
    T Initialize(); 
} 

Code mới (sẽ không biên dịch):

public interface IAsyncInitializable<out T> // ** out generic modifier...broken ** 
{ 
    /// <summary> 
    /// Boolean to indicate if class is ready 
    /// </summary> 
    bool IsInitialized { get; } 

    /// <summary> 
    /// Calls for instance to be initialized using current parameters 
    /// Driver initialization can be done in the default constructor if desired 
    /// </summary> 
    Task<T> InitializeAsync(); // ** breaks because Task<TResult> is invariant in TResult ** 
} 

có là một cách hợp lý xung quanh này mà không cần mo difying API của tôi quá mạnh? (Tiền thưởng: tại sao Task không covariant?). Không có giao diện IAwaitable, nhưng tôi cho rằng tôi có thể tạo một giao diện và tạo một phương thức mở rộng chuyển đổi thành một đối tượng nhiệm vụ được bao bọc, covariant, awiatable. Hay tôi làm sai?

+2

BTW, thậm chí nếu 'Task' là một giao diện hiệp biến, mã của bạn sẽ không biên dịch. Phiên bản chính xác sẽ là 'Task InitializeAsync();' (không có biến tố 'out' trên dòng đó). – svick

+0

Một điểm tuyệt vời. Tôi đã sửa lỗi đó trong VS, nhưng quên chỉnh sửa SO. –

Trả lời

12

Task<T> không thể biến đổi trong T, vì đó là lớp học. Chỉ giao diện và đại biểu mới có thể có phương sai chung.

Đối với việc liệu nó có đáng làm gói hay không ... Tôi đoán điều đó phụ thuộc vào số tiền bạn sử dụng hiệp phương sai trong dự án của bạn. Tôi nghi ngờ bạn sẽ tìm thấy tất cả các gói và unwrapping khó hiểu theo thời gian, phải trung thực - nếu nó không phải là quá xấu để chỉ mất hit của loại bỏ hiệp phương sai, tôi muốn làm điều đó.

+0

Cảm ơn lời khuyên! Tôi đã triển khai IAwaitable (out TResult) bằng cách sử dụng Eduasync TaskAwaiter (T) của bạn, và có thể thấy rằng việc sử dụng một giao diện riêng biệt chắc chắn không đáng để mất khả năng đọc/khả năng sử dụng. Và, tuyệt vời điểm lại: các lớp học và phương sai chung chung ... vinh dự có sai lầm của tôi chỉ ra bởi @ Jon Skeet :). Tuy nhiên, không có ITask (out T). Tôi thấy bình luận của Stephen Cleary ở đây (http://stackoverflow.com/questions/8407227/async-generic-delegate-in-c-sharp-5-0), nhưng khả năng tương thích của WinRT tương thích là một chút không hài lòng như là một minh chứng cho việc sử dụng loại bê tông. –

+1

@DavidCuccia: Bạn nên đọc trên blog của Stephen Toub về việc truyền bá bối cảnh khi nói đến những người đang chờ đợi. Nó trở nên phức tạp hơn một chút so với các chương trình của Eduasync: ( –

+0

@JonSkeet - Bất kỳ ý tưởng nào tại sao các nhà phát triển khung không thêm một 'ITask ' và chỉ thực hiện một lớp? –

4

Tôi tin rằng không bao gồm hỗ trợ trình biên dịch cho từ khóa async trên giao diện ITask là sự giám sát lớn trên phần của Microsoft. May mắn thay, nó không quá khó để làm việc xung quanh giới hạn này.

Tôi đã triển khai giao diện ITask<out TResult> có thể thay đổi được. Cách sử dụng của nó khá đơn giản.

Thông tin chi tiết có thể được tìm thấy tại địa chỉ:

https://github.com/jam40jeff/ITask

Các vấn đề liên quan