5

ObjectTValue として許可するカスタム IDictionary をセットアップしようとしています。

これは次のようになります。

public class NullTolerantDictionary<TKey, TValue> 
             : Dictionary<TKey, TValue> where TValue : class
{
    public TValue this[TKey key]
    {
        get
        {
            TValue value;
            if (TryGetValue(key, out value))
            {
                return value;
            }
            else
            {
                return DependencyProperty.UnsetValue;
            }
        }        
    }
}

これをコンパイルすると、次のように表示されます。

タイプ 'object' を 'TValue' に暗黙的に変換することはできません。

これを修正するために、型制約を次のように変更します。

where TValue : object

(objectクラスの代わりに)

次に、次のメッセージが表示されます。

制約を特別なクラス 'オブジェクト' にすることはできません

どうすればこれを回避できますか?

objectを制約にできない理由を説明するための追加クレジット。

4

2 に答える 2

7

ここでの問題は、ジェネリック型引数の制約ではなく、インデクサーのシグネチャにあります。

インデクサーは、たまたま が何であれTValue、常に を返すように文書化されています。ただし、ブランチはタイプのを返そうとします。すべての s がs であるとは限らないため、コンパイラは不平を言います (「暗黙的な変換なし」)。elseDependencyProperty.UnsetValueobjectobjectTValue

に任意の数の拘束を配置しTValueても、 に拘束できたとしても、違いはありませんobject。型引数は、より派生したものに設定することができobjectDependencyProperty.UnsetValueその型に変換することはできません。

そのような効果を達成したい場合は、次のようなpublic static読み取り専用プロパティを使用できます

public class NullTolerantDictionary<TKey, TValue> 
         : Dictionary<TKey, TValue> where TValue : class
{
    public static TValue MissingValue { get; private set; }
}

おそらく参照比較で使用できるように、インデクサーからそれを返します。

しかし、それではまだ問題が未解決のままです: TValueas として使用する値を実際に取得するにはどうすればよいMissingValueでしょうか? new()制約を配置して、静的コンストラクター内にインスタンスを作成することもできTValueますが、それでは、このクラスの可能なアプリケーションが減少します。これにより、デザインが使いにくくなり始めます。これはまさに回避しようとしていることなので、そのようにする意味はあまりありません。

于 2012-11-28T23:22:21.817 に答える
5

オブジェクトを制約にできないのはなぜですか? そして、どうすればこれを回避できますか?

あなたはそうしない。そして、あなたはする必要はありません。.NET のすべてのマネージ型は にキャストできますobject。できないもの (アンマネージ ポインターなど) がいくつかありますが、ジェネリックとは互換性がありません。

本当の問題は、私が思うに、それDependencyProperty.UnsetValueですobject。うーん....それはTValue. orでTValueあると想像してください: or の「設定されていない」値はありません。そのようなに対して任意の を返すことはできません。intbyteintbyteobjectTValue

率直に言って、TryGetValueこの拡張メソッドを使用せずに、呼び出し元に直接使用してもらいます。を使用してダミー クラス インスタンスを返す、または返すようなことを行うこともできますが、率直に言って、呼び出し元は同じことをより便利に実現するために呼び出すことができます。TValuenullTryGetValue

于 2012-11-28T23:22:06.240 に答える