2009-05-13 8 views
0

Iは、.NETリフレクターの周り突き、例えば「文字列」のような参照型のために、「==」演算子の明示的な過負荷があることに気づいた。.NET:値の型には "==" op_Equality()のデフォルトの実装はどこにありますか?

typeof(string).GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public) 

戻り値:するSystem.Reflection。 "=="演算子のMethodInfo。私はどのように正確に把握しようとしている

if((int)1 == (float)1.0) // correctly returns true 
if((int)1 == (float)1.2) // correctly returns false 

if("hi" == 3) // compiler error, plus code would throw an exception even if it ran) 

しかし、同じことは、値型のために働く:

、その実装に、あなたのようなことを行うことはできません.NETは内部的に型変換プロセスを処理するので、.NET Reflectorではop_Equality()の実装を探していましたが、「int」には.NET型がありません。

typeof(int).GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public) 

を返します。

したがって、値型の "=="演算子のデフォルト実装はどこですか? 私はリフレクション経由で呼び出すことができるようにしたい:

public bool AreEqual(object x, object y) 
{ 
    if(x.GetType().IsValueType && y.GetType().IsValueType) 
     return x == y; // Incorrect, this calls the "object" equality override 
    else 
     ... 
} 

編集#1:

私はこれを試してみましたが、それはうまくいきませんでした:

(int)1 == (float)1;       // returns true 
System.ValueType.Equals((int)1, (float)1); // returns false 

編集#2:

また、リートこの、ない愛:

object x = (int)1; 
object y = (float)1.0; 

bool b1 = (x == y);     // b1 = false 
bool b2 = ((ValueType)x).Equals(y); // b2 = false 

私はValueTypeに上でこの.Equalsオペレータが原因(.NETリフレクターからリッピング)このタイプのチェックには動作しません信じて:

ValueType.Equals(object obj) 
{ 
    ... 

    RuntimeType type = (RuntimeType) base.GetType(); 
    RuntimeType type2 = (RuntimeType) obj.GetType(); 
    if (type2 != type) 
    { 
     return false; 
    } 

    ... 

答えて

2

(int)1 ==(float)1.0の評価は、変換ルールだけの特別な==演算子に依存しません。

コンパイラは(フロート)にこれを有効にします((int型)1)==(フロート)1.0

編集: ルールがon MSDNを指定しています。あなたが探しているもの

+0

これは正しい軌道に乗っています。適切なキャストが何であるべきかを伝える方法はありますか?例えば、結果をintではなくfloatにキャストする方法をどのように知っていますか?優先順位はどこかにあるはずです... – CodingWithSpike

+0

これは正しいです。 C#(int)1 ==(float)1.0をコーディングすると、コンパイラは、(float)1.0 ==(float)1.0のIL相当を生成します。コンパイル時にintをアップキャストします。したがって、実行時に型は等しくなります。 – CodingWithSpike

1

私はあなたを推測していますあなたの構造体に継承されているValueType.Equals(object obj)を探しています。反射を使用してすべてのフィールドを比較します。

+0

これは典型的なケースです。はるかに一般的にビットごとの比較を行うでしょう – JaredPar

+0

上記の私の編集#2を私のオリジナルの投稿に見てください。 – CodingWithSpike

2

が、これは単に値のビット比較によってビットを行い、多くのケースではValueType.Equals

です。場合によっては、フィールドを検証するためにリフレクションを使用します。

EDIT

あなたはC#が値型を比較してどのように混乱し、どのようにしています。Netは値の型を比較します。 ValueType.Equalsは、同じタイプの値型オブジェクトを比較するために使用される.NETの関数です。 C#は、最終的にその関数を呼び出すコードを出力します。しかし、それは "int"と "float"で呼び出されません。代わりに、最初に両方の値をいずれかの値(double)の精度が失われない型に変換し、結果のdouble値を比較します。これが行動の違いを見る理由です。

+0

私はそれを試みましたが、期待どおりに動作しませんでした。 ValueType.Equals((int)1、(float)1);偽を返す:(int)1 ==(float)1; – CodingWithSpike

+0

@ rally25rs、あなたが書いたコードはAFAICTをコンパイルしません。 ValueType.Equalsはインスタンスメソッドであり、1つのパラメータ – JaredPar

+0

を受け取るだけです。私は、Objectから継承されたValueType.Equals(オブジェクト、オブジェクト)と、ValueTypeにあるValueType.Equals(オブジェクト)があることに気付きました。私は間違ったものを呼んでいた。おっとっと! :) – CodingWithSpike

1

My answer別の質問には、ロータの実装が提供されます。実際のコードはネイティブコードとしてCLRに実装されています。

具体的に:

// Compare the contents (size - vtable - sink block index). 
BOOL ret = memcmp(
    (void *) (pThisRef+1), 
    (void *) (pCompareRef+1), 
    pThisRef->GetMethodTable()->GetBaseSize() - sizeof(Object) - sizeof(int)) == 0; 
2

どこにあるの値の種類の==op_Equalityのためのデフォルトの実装?

値タイプにはデフォルト値==はありません。独自の値型

struct JustAnotherValueType 
{ 
    public readonly int Field; 
    public JustAnotherValueType(int f) { Field = f; } 
} 

を書いてみ二つの値xとあなたのタイプのyしてください。それらとx == yと言ってみてください。それはコンパイルされません。あなた

(object)x == (object)y 

を言うことができるが、それはy(ボックス2)にxのボクシング(のは1箱にそれを呼びましょう)とボクシングを実行して、2つのボックスの参照比較を実行します。したがって、常にfalseを返します。したがって、それは役に立ちません。それはの2つの間に==を使用すると、過負荷が自動的に選択されない理由です。JustAnotherValueType

intfloatはどうなっていますか?あなたはC#の==とそれらを比較することができ、それらはop_Equalityメソッドを持っていませんか?これらの過負荷はthe C# Language Specificationで定義されていると説明します。セクションの整数比較演算子およびの浮動小数点比較演算子を参照してください。

実際、これらの演算子は.NET構造体のメンバーとして存在しませんが、C#言語仕様で定義されており、C#コンパイラは動作を模倣するために有効なILを生成する必要があります。

ところで、System.Objectにはop_Equalityもありません。これもC#で定義されています。 参照型等価演算子を参照してください。 System.ObjectにはReferenceEqualsというメソッドがあり、コンパイラはこのオーバーロードを==に変換することを選択できます。また、仕様のこのセクションではx == yxまたはyでボクシングを実行しないように制限があることにも注意してください。

DateTime,TimeSpan、およびGuidのようなC#仕様には記載されていませんが、==を使用するのはどうでしょうか?答えは、doop_Equalityのメンバーです。

結論:C#言語仕様は、C#の実装を持つことが必要であることを==過負荷の多くを定義し、これらの過負荷の一部は、intfloatobjectを伴います。

備考:仮想インスタンスメソッドEquals(object)は、objectで定義され、すべての値タイプで継承されます。このメソッド自体をオーバーライドしない構造体の場合は,のSystem.ValueTypeが使用されます。それは価値によって比較されます。したがって、上記のようなxyの場合、x.Equals(y)は正常に動作します。 Equalsは仮想インスタンスメソッドです。他方、==は、staticであり、2つのオペランドのコンパイル時のタイプに基づく過負荷解決が実行される(「仮想ディスパッチ」なし)。

関連する問題