42

次のコードはコンパイルされません。

string foo = "bar";
Object o = foo == null ? DBNull.Value : foo;

エラー1「System.DBNull」と「string」の間に暗黙の変換がないため、条件式のタイプを判別できません

これを修正するには、次のようなことを行う必要があります。

string foo = "bar";
Object o = foo == null ? DBNull.Value : (Object)foo;

これは確かに合法であるため、このキャストは無意味に思えます。

string foo = "bar";
Object o = foo == null ? "gork" : foo;

三項分岐のタイプが異なる場合、コンパイラは値をタイプオブジェクトに自動ボックス化しないようですが、同じタイプの場合、自動ボックス化は自動的に行われます。

私の考えでは、最初のステートメントは合法である必要があります...

コンパイラがこれを許可しない理由と、C#の設計者がこれを選択した理由を誰かが説明できますか?これはJavaでは合法だと思います...これは確認していませんが。

ありがとう。

編集: JavaとC#がこれを異なる方法で処理する理由、これを無効にするC#のシーンの下で何が起こっているのかを理解してください。私は三元の使い方を知っていて、例をコーディングするための「より良い方法」を探していません。C#の3値のルールは理解していますが、なぜ...

編集(Jon Skeet):この質問にはボクシングが含まれていないため、「autoboxing」タグを削除しました。

4

3 に答える 3

70

コンパイラーは、2番目と3番目のオペランドのタイプが同じであるか、一方が他方に暗黙的に変換可能であることを要求します。あなたの場合、タイプはDBNullとstringであり、どちらも暗黙的に他に変換できません。それらのいずれかをオブジェクトにキャストすると、それが解決されます。

編集:Javaでは確かに合法のようです。メソッドのオーバーロードに関しては、どうすればよいのかよくわかりません... JLSを見たばかりですが、互換性のない参照が2つある場合の条件のタイプは非常に不明です。関係するタイプ。C#の作業方法は、ときどきイライラする場合がありますが、IMOの方が明確です。

C#3.0仕様の関連セクションは、条件演算子である7.13です。

?:演算子の2番目と3番目のオペランドは、条件式のタイプを制御します。XとYを2番目と3番目のオペランドのタイプとします。それで、

  • XとYが同じタイプの場合、これは条件付きのタイプです
  • それ以外の場合、暗黙の変換(§6.1)がXからYに存在するが、YからXには存在しない場合、Yは条件式のタイプです。
  • それ以外の場合、YからXへの暗黙の変換(§6.1)が存在するが、XからYへの変換は存在しない場合、Xは条件式のタイプです。
  • そうしないと、式の種類を判別できず、コンパイル時エラーが発生します。
于 2008-10-14T18:35:21.180 に答える
18

DBNull.Valueタイプを返しますDBNull

タイプをにしたいとしますstring

stringできますが、できませnullDBNull

コードでは、equalsの右側のステートメントは、オブジェクトに割り当てる前に実行されます。

基本的に使用する場合:

[condition] ? true value : false value;

.Netでは、trueオプションとfalseオプションの両方を、割り当てる前に、暗黙的に同じタイプに変換できる必要があります。

これは、C#が型安全性をどのように処理したかによるものです。たとえば、次のことが有効です。

string item = "item";

var test = item != null ? item : "BLANK";

C#3は動的型をサポートしていませんが、テストとは何ですか?C#では、すべての割り当ても戻り値を持つステートメントであるため、varC#3では構文は新しいものですが、equalsの右側のステートメントは常に単一の型に解決する必要があります。

C#4以降では、動的型を明示的にサポートできますが、ここでは役に立たないと思います。

于 2008-10-14T18:31:54.493 に答える
10

ところで、あなたのコードは、条件演算子をまったく使用する必要のない特殊なケースです。代わりに、null 合体演算子の方が適切です (ただし、キャストが必要です)。

object result = (object)foo ?? DBNull.Value;
于 2008-10-14T18:56:19.967 に答える