11

私はC#5.0非同期プログラミングでの作業を本当に楽しんでいます。ただし、TAPモデルと一致するように古いコードを更新すると、問題が発生する場所がいくつかあります。

Task<TResult>そのうちの1つです-TResultで共変ではない理由は正確にはわかりませんが、共変インターフェイスを更新して同期パターンから非同期パターンに移行しようとすると、問題が発生します。

古いコード:

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();
}

新しいコード(コンパイルされません):

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 **
}

APIを大幅に変更せずにこれを回避する合理的な方法はありますか?(ボーナス:なぜタスクは共変ではないのですか?)IAwaitableインターフェースはありませんが、IAwaitableインターフェースを作成して、ラップされた共変で実行可能なタスクオブジェクトに変換する拡張メソッドを作成できると思います。それとも私はそれを間違っていますか?

4

2 に答える 2

14

Task<T>Tクラスであるため、で共変にすることはできません。一般的な差異を持つことができるのは、インターフェースとデリゲートのみです。

ラッピングを行う価値があるかどうかについては...プロジェクト内で共分散をどれだけ使用するかによって異なります。正直なところ、時間の経過とともにすべてのラッピングとアンラッピングが混乱することに気付くと思います。共分散を削除するだけでも悪くないのであれば、そうします。

于 2012-08-30T20:18:45.307 に答える
7

ITaskインターフェイスにasyncキーワードのコンパイラサポートを含めないことは、Microsoft側の大きな見落としだったと思います。幸い、この制限を回避するのはそれほど難しくありません。

ITask<out TResult>共変の待機可能なインターフェイスを実装しました。その使用法は非常に簡単です。

詳細については、次を参照してください。

https://github.com/jam40jeff/ITask

于 2014-10-15T22:07:24.567 に答える