13

これは、C# 言語、または少なくともその言語が Visual Studio でどのように実装されているかについての質問です。

暗黙の演算子を System.DateTime に定義するクラス Foo があるとします。

public static implicit operator DateTime(Foo item)

次のコードを検討してください。

Foo foo = SomeMethodWhichCanReturnNull();    
DateTime?  dtFoo = foo;

私が期待すること:Fooからへ の変換がないことを訴えるコンパイルの失敗DateTime?

私が見つけたもの:コンパイラは実際に定義された暗黙の演算子をFootoから呼び出し、 DateTimenullが渡されるとクラッシュします(コンバーターがnullに応答できる唯一の方法です)。

もちろん、回避策は定義することです

public static implicit operator DateTime?(Foo item)

しかし、なぜ私はこれをしなければならないのですか?DateTimeDateTime?2つの異なるタイプではありませんか?

4

5 に答える 5

13

まず、C# 言語仕様では、組み込みの暗黙的な変換をユーザー定義の暗黙的な変換のどちらの側にも挿入できると規定されています。したがって、ユーザー定義の から への暗黙的な変換があった場合、ShapeからへのGiraffe変換が自動的に許可されます。あなたの場合、オペランドが type であると仮定して、追加の変換は片側にのみ挿入されます。任意の型から対応する null 許容型への暗黙的な変換があります。2 番目のユーザー定義の変換が挿入されることはありません。どちらの側にも組み込み変換のみを挿入できます。SquareMammalSquare --> Shape --> Giraffe --> MammalFoo

(これはユーザー定義の明示的な変換にも当てはまることに注意してください。明示的な変換はどちらの側にも挿入できます。)

第二に、仕様に違反しています。これは、ユーザー定義の暗黙的な変換が例外をスローしてはならないことを強く示唆しています。操作が成功することを保証できない場合は、型を変更するか、明示的な変換にします。

3 番目に、ユーザー定義の暗黙的な変換の両方の型が null 非許容の値型である場合、C# コンパイラは "リフトされた" 変換を自動的に定義することに興味があるかもしれません。構造体型 S から構造体型 T へのユーザー定義の暗黙的な変換がある場合、S から「持ち上げられた」変換が得られますか? Tに?のセマンティクスで無料でs.HasValue ? new T?((T)s.Value) : new T?()

この主題は、C# 仕様の中でも複雑な分野の 1 つであるため、正確な詳細を知りたい場合は、注意深く読むことをお勧めします。

于 2013-05-31T17:29:50.963 に答える