c#等于

 

不重载 operator ==(int、float、.... object等)

class Program
{
    static void Main(String[] args)
    {
        int num1 = 5;
        int num2 = 5;

        Console.WriteLine(num1.Equals(num2));
        Console.WriteLine(num1 == num2);
    }
}

public struct Int32: IComparable, IFormattable, IConvertible, IComparable<int>, IEquatable<int>

如果您以前从来没有接触过IL指令,不过没关系,在这里您不需要理解所有的指令,我们只是想了解这两个比较方式的差异。

  您可以看到这样一行代码:

1   IL_0008:  call       instance bool [mscorlib]System.Int32::Equals(int32)

  在这里调用的是int类型Equals(Int32)方法(该方法是IEquatable<Int>接口的实现)。

  现在再来看看使用==运算符比较生成的IL指令:

1   IL_0015:  ceq

  您可以看到,==运行符使用的是ceq指令,它是使用CPU寄存器来比较两个值。C#==运算符底层机制是使用ceq指令对基元类型进行比较,而不是调用Equals方法。

 

如果重载 operator ==(string等):重载相当于添加了一个比较的静态方法

class Program
  {
     static void Main(String[] args)
     {
          string s1 = "Sweet";
         string s2 = String.Copy(s1);
 
         Console.WriteLine(ReferenceEquals(s1, s2));
         Console.WriteLine(s1 == s2);
         Console.WriteLine(s1.Equals(s2));
     }
 }

sealed class String : IComparable, ICloneable, IConvertible, IEnumerable, IComparable<string>, IEnumerable<char>, IEquatable<string>

在这里我们没有看到ceq指令,对String类型使用==运算符判断相等时,调用的是一个op_equality(string,string)的新方法,该方法需要两个String类型的参数,那么它到底是什么呢?答案是String类型提供了==运算符的重载。在C#中,当我们定义一个类型时,我们可以重载该类型的==运算符。所以我们重载操作符号也是一样。

 

 

System.Object provides the following methods:

public static bool ReferenceEquals(object objA, object objB)
{
    return objA == objB;
}

public static bool Equals(object objA, object objB)
{
    return objA == objB || (objA != null && objB != null && objA.Equals(objB));
}
         
public virtual bool Equals(object obj)
{
    return RuntimeHelpers.Equals(this, obj);
}

 

string(不是继承自object) like this:


public static bool operator ==(string a, string b)
{
    return Equals(a, b);
}

public static bool operator !=(string a, string b)
{
    return !Equals(a, b);
}

public static bool Equals(string a, string b)
{
    if ((object)a == b) //转化为obejct==object,进行一次装箱操作
    {
        return true;
    }
    if (a != null && b != null)
    {
        if (a.Length != b.Length)
        {
            return false;
        }
        return EqualsHelper(a, b);
    }
    return false;
}
private unsafe static bool EqualsHelper(string strA, string strB)
{
    int num = strA.Length;
    fixed (char* ptr = &strA.m_firstChar)//Represents a character as a UTF-16 code unit(两字节)
    {
        fixed (char* ptr3 = &strB.m_firstChar)
        {
            char* ptr2 = ptr;
            char* ptr4 = ptr3;
            while (num >= 12)
            {
                if (*(long*)ptr2 != *(long*)ptr4)
                {
                    return false;
                }
                if (*(long*)(ptr2 + 4) != *(long*)(ptr4 + 4))
                {
                    return false;
                }
                if (*(long*)(ptr2 + 8) != *(long*)(ptr4 + 8))
                {
                    return false;
                }
                ptr2 += 12;
                ptr4 += 12;
                num -= 12;
            }
            while (num > 0 && *(int*)ptr2 == *(int*)ptr4)
            {
                ptr2 += 2;
                ptr4 += 2;
                num -= 2;
            }
            return num <= 0;
        }
    }
}
 

We can use like this....

Use object.ReferenceEquals(person1, null) instead of the == operator:

public static bool operator ==(Person lhs, Person rhs)
{

  bool leftNull = System.Object.ReferenceEquals(lhs, null);
  bool rightNull = System.Object.ReferenceEquals(rhs, null);
  if (leftNull || rightNull)
  {
    return leftNull && rightNull;
  }

// Return true if the fields match:
    return lhs.Equals(rhs);
}

public static bool operator !=(Person lhs, Person rhs)
{
    return !(lhs == rhs);
}

 

posted @ 2018-09-28 23:35  何人之名  阅读(575)  评论(0)    收藏  举报