2

今日、私はこの興味深い状況に出くわしました:

var a = new HashSet<Object> { 1.0, 2.0, 3.0 };
a.Contains(1);     //False
a.Contains(1.0);   //True

もちろん、これはこれの一般的なバージョンにすぎません。

Object b = 2.0;
b.Equals(2);            //False
b.Equals(2.0);          //True

この理由は、私が書く2.0 == 2と、C# コンパイラが整数から倍精度へのキャストを秘密裏に挿入し、オブジェクト中間体を使用することで、コンパイラがこれを行うのに十分な情報を持っていないためであることに気付きました。

私の質問は、比較のために整数を2倍にするのに十分な情報がランタイムにないのでしょうか? C# コンパイラが、暗黙的な変換が必要であると判断した場合、JIT が同様の動作を行うべきではないのはなぜでしょうか?

4

3 に答える 3

4

C# は、言語仕様で動作するように動作する必要があります。これは、言語仕様を実装するだけでよい Jitter とは関係ありません。

C# 言語仕様は、どのように機能する==必要があるかを示しています。

CLR仕様は、どのように機能するEquals()必要があるかを示しています。

実際、.Net 1.1 と .Net 2.0 の間に興味深い変更が加えられました。

.Net 1.1 では、3f.Equals(3) == false.

.Net 2.0 では、3f.Equals(3) == true.

これは、 のオブジェクト比較バージョンと同じではありませんEquals()。この種のことがいかに微妙かを示しています。

これに関する興味深い (しかし非常に古い) ブログ: http://blogs.msdn.com/b/jmstall/archive/2005/03/23/401038.aspx

実際には、あなたの質問に関連する詳細がいくつかあるので、読む価値があります。

于 2013-05-21T22:22:40.613 に答える
2

2.0 == 2C# は、ECMA-334 標準で定義されている、を処理するための特定のセマンティクスを持つ特定のプログラミング言語です。共通言語ランタイム (CLR) は、ECMA-335 標準によって定義された実行環境であり、C# ソース コードではなくバイトコードで動作します。これらのセマンティクスは多くの点で異なるため、ランタイム部分実装して、これらのタイプの比較の拡大変換を自動的に実行することもできましたが、実際にはそのようには行われませんでした。

ここで行われる特定の比較はたまたま を呼び出してDouble.Equals(Object)おり、それが返されます

trueobjがのインスタンスでDoubleあり、このインスタンスの値と等しい場合。それ以外の場合は false。

于 2013-05-21T22:22:15.873 に答える
0

これは、特定の解決策を探しているというよりも、コミュニティの質問のように感じます。でも喜んで加重します。

まず、ご存知かもしれませんが、二重等価比較はすでに危険であるということから始めます。に関する情報は山ほどあります

if(doubleNum == doubleNum2)

しかし、親戚ではない異なるタイプの2つのオブジェクトが同等であるべきかどうかも考慮してください。コードを書いている間、コンパイラはいくつかの基本的なアイデアを想定できます。しかし、ほとんどの .Equals(object) メソッドが最初に行うことは、型の互換性をチェックすることであり、互換性がない場合は false が返されます。b.Equals(2) は double ではない int Type が渡されると想定しているため、ここではこれが当てはまると思います。

double.Equals(object) メソッドを見ると、最初に、渡されたオブジェクトが double かどうかをチェックしていることに気付くでしょう。Int32 であるため、関数は false を返します。

他の答えは、実装がどのようになっているのかという理由によります。上記は、ランタイムがどのように動作するかを説明する必要があります。

于 2013-05-21T22:16:11.343 に答える