在 C# 中 Object 是所有类的基类,所有的结构和类都直接或间接的派生自它。前面这段话可以说所有的 C# 开发人员都知道,但是我相信其中有一部分程序员并不清楚甚至不知道我们常用的 ToString 、 Equals 和 GetHashCode 虚方法都来自于 Object 类,并且我们可以对它们进行重写。重写这三个虚方法可以说在项目开发中经常用到,只不过大部分开发人员并未留意这三个虚方法可以重写,而是自己写方法来实现。
下面我就来具体讲解一下它们三个应该怎么重写。在这里我需要说明的是本篇文章会大量涉及到设计规范和设计要求,代码只是作为辅助理解的形式出现,因此文章中的所有代码将会以代码段的形式出现。
ToString 重写是这三种方法中重写最简单的,也是最常用的。但是有一部分开发人员认为重写 ToString 方法意义不大,那么我在这里要说的是这种想法是错误的。当我们在对象上调用 ToString 时默认返回的是类的完全限定名称,比如说我们在 System.IO.File 对象上调用这个方法,就会返回字符串 System.IO.File ,这个结果往往并不是我们所需要的结果并且这个结果也没有什么意义。例如我们在一个 User 类中重写 ToString 方法,每次调用 User.ToString() 时返回 "XXX今年XX岁",如果我们不重写 ToString 方法的话就得不到我们想要的结果。因此我们必须重写,这时我们就可以这么写。
public class User
{
public int Id {get;set;}
public string Name {get;set;}
public int Age {get;set;}
public string Sex {get;set;}
public override string ToString()
{
return $"{Name}今年{Age}岁!";
}
}
重写之后我们就可以得到我们想要的输出内容了。虽然重写 ToString 可以得到我们想要的内容,但是我们不能在任何情况下都重写 ToString, 只有在以下三种情况下方可重写 ToString :
在上面三种情况下重写 ToString 我们还需要遵循一些设计规范,这些设计规范并不是微软所定义的,而是开发人员在开发过程中总结出来的:
到这里为止我们讲解完了 ToString 重写的方法以及规则。相对来说 ToString 方法重写是 Object 虚方法重写中十分简单的部分,作为开发人员只需按照我前面多说的规则、方法以及实际情况来重写即可。
在 C# 中如果对两个对象进行相等判断,一共有两种情况分别是:判断两者的值相等 或者 判断两者的引用地址相同 。一般情况下我们需要对值类型对象判断值相等,对引用类型对象判断指向地址相同。Equals 就是用来对引用类型对象判断指向地址是否相同的。对于重写 Equals 方法,很多开发人员认为易如反掌,但是在开发中往往忘记一些很重要的细节,这些细节对于程序来说至关重要,下面我将一一进行详细讲解。
同一和相等
所谓的同一指的是两个对象如果引用的是同一个实例,那么我们就说这两个对象具有同一性。在 C# 中我们可以利用 object 类或者它的派生类中的 ReferenceEquals 静态方法来判断对象之间的同一性。但是同一只是相等的一种,因为在某些情况下两个对象的部分值或者全部值相等但引用不同,我们也可以说它们具有相等性。下面我们来看一个例子,这个例子通过重写相等性来实现两个对象的相等性。
class Program
{
static void Main(string[] args)
{
Student s1 = new Student
{
Age = 12,
Id = 1,
Name = "小明"
};
Student s2 = new Student
{
Age = 13,
Id = 1,
Name = "小明"
};
if (Student.ReferenceEquals(s1, s2))
{
Console.WriteLine("是同一个学生");
}
else
{
Console.WriteLine("不是同一个学生");
}
Console.Read();
}
}
class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public static bool ReferenceEquals(Student s1, Student s2)
{
if (s1.Equals(s2) ||
object.ReferenceEquals(s1, s2) ||
s1.Id==s2.Id
s1==s2)
{
return true;
}
else
{
return false;
}
}
}
从上述代码中我们可以看出,虽然 s1 和 s2 引用是不相等的,但是这两个对象使用了相同的 Id ,因此我们认为 Id 相同的学生就是同一个学生。这么做可以确保数据库中不会出现重复的录入。
Tip:只有引用类型才会可能出现引用相等的情况,对于值类型来说调用 ReferenceEquals 方法永远返回的是 false ,因为值类型转换成 object 时是需要装箱的,即是传递的两个参数是同一个值,也会返回 false 。
Equals
判断两个对象是否相等,可以使用 Equals ,通过它可以判断出两个对象是否具有相同的数据。在 object 中这个方法只是调用了 ReferenceEquals 方法来判断同一性,因此在必要的时候我们必须重写 Equals 方法。一般来说重写 Equals 方法常用的步骤如下:
Tip: 如果类型是密封类型,那么第三步可以省略掉。
我们不仅需要按照上述的步骤重写 Equals 方法,还需要注意如下几点:
在上一小节中我们也注意到在重写 Equals 过程中我们需要重写 GetHashCode 方法。 所谓 Hash Code 就是用来生成和对象值对应的数字,从而高效的平衡哈希表的作用。 重写 GetHashCode 方法是比较困难的,下面我就来详细讲解一下重写规则、方法和注意事项。重写 GetHashCode 方法需要从性能、安全方面考虑,同时也需要满足一些要求。
本篇文章主要讲解了重写 object 中虚方法的知识,其中涉及到了很多 C# 核心内容,这些内容和知识在实际开发中用的很多,但是大多数开发人员并不在意,因此我希望读者阅读完我这篇文章后能对这些内容和知识有初步的了解。
本文由博客一文多发平台 OpenWrite 发布! 更多文章请扫码关注公众号:“喵叔呦”
联系客服