ジェネリック型の暗黙的な演算子
-
26-09-2019 - |
質問
次のような暗黙的な演算子を使用すると何か問題がありますか?
//linqpad c# program example
void Main()
{
var testObject = new MyClass<int>() { Value = 1 };
var add = 10 + testObject; //implicit conversion to int here
add.Dump(); // 11
}
class MyClass<T>
{
public T Value { get; set; }
public static implicit operator T (MyClass<T> myClassToConvert)
{
return myClassToConvert.Value;
}
}
この方法でオブジェクトのインスタンスを値型として扱うことができると考えていましたが、この例を見たことがなかったので、おそらく理由があるのではないかと思いました ない 誰かに指摘されるようなことをするには?
実際のコードでは、これをデータ抽象化レイヤーの一部として実行して、基礎となるデータを説明する情報を含むオブジェクトを返すことができるようにすることを考えていましたが、必要な情報がすべて揃っている場合には、ロジック コードがそれを値型として扱うことができるようにします。は値であり、同時にジェネリックを使用してすべてを適切に保ち、型を安全に保ちます。
解決
次のすべてが当てはまる場合:
全て あなたの考えられる値
MyClass<T>
タイプ(含む)null
値型でない場合は、有効な値にマップします。T
暗黙的な演算子は決してスローしません(
null
!)暗黙的な変換は意味的に意味があり、クライアント プログラマを混乱させることはありません。
それなら何も問題ありません。もちろんあなた できた これら 3 つのいずれかを実行しても、それは悪い設計になります。特に、スローする暗黙的な演算子は、それが呼び出される場所では呼び出されていることが示されないため、デバッグが非常に困難になる可能性があります。
たとえば、次のように考えてみましょう T?
への暗黙的な変換はありません T
(どこ T
もちろん、値型です)。このような暗黙的な演算子があった場合は、次のときにスローする必要があります。 T?
変換する明らかな値がないため、null です。 null
それは理にかなっています どれでも 値の型 T
.
暗黙的な演算子がスローする問題のデバッグに苦労した例を示します。
public string Foo()
{
return some_condition ? GetSomething() : null;
}
ここ、 GetSomething
ユーザー定義の暗黙的な変換を持つ、私が作成した型の何かが返されました。 string
. 。私が作りました 絶対に確かに それ GetSomething
決して戻れなかった null
, 、それでも私は NullReferenceException
!なぜ?なぜなら、上記のコードは ない に相当
return some_condition ? (string)GetSomething() : (string)null;
しかし、に
return (string)(some_condition ? GetSomething() : (Something)null);
これで、どこにあるかがわかります。 null
から来た!
他のヒント
これは偉大なパターンです。ジャストタイプT
の変数としてそれを使用するためには、あなたが明示的T
にキャストしなければならないことを心に留めておく、またはタイプT
の変数に割り当てます。キャストは、メソッド呼び出しとT
を取る(例えば、あなたのほかの例として)他のものに自動的に行われます。