C#中 Equals和= =的区别
前言:最近感觉技术进步实在是太慢,一直被游戏缠身不能自拔哈哈,但是游戏打多了真的是感觉整个人浮躁的不行,所以我现在要去游戏多写代码多看书,今天在博客园中看到一个前辈去阿里面试的面试题,由浅入深的问了很多问题,所以我想这就是个契机,可以通过答题来学习知识让自己进步,闲话少说,我们正式开始
0.复习堆栈知识
因为要通过引用类型和值类型分情况讨论,所以对C#中堆栈知识的复习还是有必要的
简单说结论:
1·栈通常保存着我们代码执行的步骤,而堆上存放的则多是对象,数据等。
2·值类型存放在栈上,引用类型存放在堆上,但是会在栈中生成一个指针。
3·一个值类型被声明在一个方法体外并且在一个引用类型中,那它就会在堆上进行分配。
1·分情况讨论
在C#中,讨论这个问题要分三种情况
- 值类型
- 引用类型
- String 字符串类型
1.1值类型
在值类型中,Equals都是通过==来实现的,类似于:
public override bool Equals(object obj)
{
return ((obj is bool) && (this == ((bool) obj)));
}
所以在值类型中,Equals和==其实是完全一样的东西。
1.2引用类型
本质上来说,Equals都是集成自Object的Equals方法,通过反编译,可以看到Equals内部的逻辑,即:引用相同返回true,或者两个对象都不为空的情况下,内部值相同,也返回true
public static bool Equals(object objA, object objB)
{
return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB)));
}
所以在值类型中,==是判断引用是否相同,而Equals判断内部值是否相同,当然如果引用相同内部值肯定也相同。
1.3 String字符串类型
字符串类型比较特殊,是因为在string类的内部对Equals和==两个方法都进行了重写,是的你没看错,两个都重写,所以很特殊
public static bool operator ==(string a, string b)
{
return Equals(a, b);
}
public static bool Equals(string a, string b)
{
if (a == b)
{
return true;
}
if ((a == null) || (b == null))
{
return false;
}
if (a.Length != b.Length)
{
return false;
}
return EqualsHelper(a, b);
}
可以看到最后全部都定位到了EqualsHelper这个方法里面,所以在string里面,Equals和==的意义是相同的,全都是表示判断string的内部内容是否相同。(EqualsHelper方法的代码在文末)
结语和总结
- ==判断引用是否相同
- Equals判断内部值是否相同
- 不同情形下,具体情况稍有差别
用了一整个晚上的时间把这个知识梳理研究明白,感觉时间过得很慢,也过得挺有意义的,还复习了markdown的语法,希望这是我改变自己生活的一个好的开始,预告下一篇文章的主题是:“什么时候捕获异常,什么时候抛出异常”
private static unsafe bool EqualsHelper(string strA, string strB)
{
int length = strA.Length;
fixed (char* chRef = &strA.m_firstChar)
{
fixed (char* chRef2 = &strB.m_firstChar)
{
char* chPtr = chRef;
char* chPtr2 = chRef2;
while (length >= 10)
{
if (*(((int*) chPtr)) != *(((int*) chPtr2)))
{
return false;
}
if (*(((int*) (chPtr + 2))) != *(((int*) (chPtr2 + 2))))
{
return false;
}
if (*(((int*) (chPtr + 4))) != *(((int*) (chPtr2 + 4))))
{
return false;
}
if (*(((int*) (chPtr + 6))) != *(((int*) (chPtr2 + 6))))
{
return false;
}
if (*(((int*) (chPtr + 8))) != *(((int*) (chPtr2 + 8))))
{
return false;
}
chPtr += 10;
chPtr2 += 10;
length -= 10;
}
while (length > 0)
{
if (*(((int*) chPtr)) != *(((int*) chPtr2)))
{
break;
}
chPtr += 2;
chPtr2 += 2;
length -= 2;
}
return (length <= 0);
}
}
}