首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >.NET:值类型的"==“op_Equality()的默认实现在哪里?

.NET:值类型的"==“op_Equality()的默认实现在哪里?
EN

Stack Overflow用户
提问于 2009-05-13 19:30:25
回答 5查看 3.4K关注 0票数 0

我在.NET反射器中四处寻找,并注意到对于诸如"String“这样的引用类型,"==”操作符有一个显式重载:

代码语言:javascript
复制
typeof(string).GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public)

返回: System.Reflection.MethodInfo表示"==“运算符。

由于它的实现,您不能这样做:

代码语言:javascript
复制
if("hi" == 3)  // compiler error, plus code would throw an exception even if it ran)

但是,对于值类型也是一样的:

代码语言:javascript
复制
if((int)1 == (float)1.0)  // correctly returns true
if((int)1 == (float)1.2)  // correctly returns false

我试图弄清楚.NET内部是如何处理类型转换过程的,所以我在.NET Reflector中寻找op_Equality()的实现,但是"int“没有。

代码语言:javascript
复制
typeof(int).GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public)

返回null。

那么,值类型的"==“运算符的默认实现在哪里?我想通过反射来称呼它:

代码语言:javascript
复制
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:

我试过了,但没用:

代码语言:javascript
复制
(int)1 == (float)1;                          // returns true
System.ValueType.Equals( (int)1, (float)1 ); // returns false

编辑2:

也尝试过这个,但没有爱:

代码语言:javascript
复制
object x = (int)1;
object y = (float)1.0;

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

我认为,由于这种类型检查(从.Equals反射器中取出),ValueType上的这个.NET操作符无法工作:

代码语言:javascript
复制
ValueType.Equals(object obj)
{
    ...

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

    ...
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-05-13 19:38:30

(int)1 == (float)1.0的计算不依赖于任何特殊的==操作符,而只是转换规则。

编译器将将其转换为(浮点数)((Int)1) == (浮点数)1.0。

编辑:规则指定为论MSDN

票数 2
EN

Stack Overflow用户

发布于 2009-05-13 19:39:10

你要找的是ValueType.Equals

在许多情况下,这只是一点一点地比较值。但在某些情况下,它将使用反射来验证字段。

编辑

您混淆了C#如何比较值类型以及.Net如何比较值类型。ValueType.Equals是.Net中的一个函数,用于比较具有相同类型的值类型对象。C#将发出最终调用该函数的代码。但它并没有用"int“和"float”来称呼它。相反,它首先将这两种类型转换为一种类型,这种类型对任何一个值( double )都不具有精确性,然后比较所得到的双值。这就是为什么你看到不同的行为。

票数 2
EN

Stack Overflow用户

发布于 2013-01-16 23:17:53

值类型的== op_Equality的默认实现在哪里?

值类型没有默认的==。尝试编写自己的值类型。

代码语言:javascript
复制
struct JustAnotherValueType
{
  public readonly int Field;
  public JustAnotherValueType(int f) { Field = f; }
}

使两个值xy与您的类型相同。试着和他们说x == y。它不会编译。你可以说

代码语言:javascript
复制
(object)x == (object)y

但是,这将在x上执行装箱(我们称之为方框1),在y上执行装箱操作(方框2),然后对这两个框执行引用比较。因此,它总是返回false。因此,这是无用的,这也是为什么在两个==(object x, object y)之间使用==时不会自动选择重载JustAnotherValueType的原因。

那么intfloat是怎么回事?您可以将它们与==在C#中进行比较,而它们没有op_Equality方法?!其解释是这些重载是由C#语言规范定义的。参见Integer比较运算符和浮点比较运算符.

因此,事实是,虽然这些操作符并不作为.NET结构的成员存在,但C#语言规范定义了它们,C#编译器必须生成一些有效的IL来模拟它们的行为。

顺便说一下,System.Object也没有op_Equality。它也是由C#定义的。请参阅引用类型相等操作符一节。请注意,System.Object有一个ReferenceEquals方法,编译器可以选择将==重载转换为该方法。还请注意,规范的这一部分提供了限制,使x == y永远不会在xy上执行装箱操作。

DateTimeTimeSpanGuid之类的值类型如何?这些类型在C#规范中没有提到,但是使用==是合法的。答案是,这些doop_Equality成员。

结论: C#语言规范定义了C#实现所需要的大量==重载,其中一些重载涉及intfloatobject

注意:虚拟实例方法Equals(object)是在object中定义的,并由所有值类型继承。对于本身不覆盖此方法的结构,将使用System.ValueType中的System.ValueType。它按价值进行比较。因此,有了上面这样的xyx.Equals(y)就可以正常工作了。Equals是一个虚拟实例方法。另一方面,==是一个基于两个操作数编译时类型执行重载解析的static“方法”(没有“虚拟调度”)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/859938

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档