CS3L23——object中的方法

本章代码关键字

1
2
3
4
5
6
7
8
9
10
//静态方法
Object.Equals() //用来判断两个值是否相等,最终的判断权交给左侧对象的Equals成员方法(注意不是静态方法!)
Object.ReferenceEquals() //比较两个对象是否是相同的引用,主要是用来比较引用类型的对象,值类型对象返回值始终是 false
//成员方法
object.GetType() //在运行时获取对象的类型
object.MemberwiseClone() //该方法用于获取对象的浅拷贝对象,它会返回一个新的对象,新旧对象的引用类型成员都指向同一个数据
//虚方法
object.Equals() //默认实现还是比较两者是否为同一个引用,可以重写该方法,定义自己的比较相等的规则
object.GetHashCode() //获取对象哈希码,可以通过重写该函数来自己定义对象的哈希码算法
object.ToString() //用于返回当前对象代表的字符串,默认会返回命名空间.类名,可以重写以返回自定义内容

object中定义的方法

查看 object​ 的定义,可以看到 object​ 有如下的方法

1
2
3
4
5
6
7
8
9
10
11
12
public class Object
{
public Object();
~Object();
public static bool Equals(Object? objA, Object? objB);
public static bool ReferenceEquals(Object? objA, Object? objB);
public virtual bool Equals(Object? obj);
public virtual int GetHashCode();
public Type GetType();
public virtual string? ToString();
protected Object MemberwiseClone();
}

object中的静态方法

Equals(静态方法)

静态方法 Equals​,用来判断两个值是否相等,最终的判断权 交给左侧对象的 Equals​ 成员方法(注意不是静态方法!)
不管值类型还是引用类型都会按照左侧对象 Equals​ 成员方法会在来进行比较

引用类型,如果不重写其 Equals​ 成员方法,则判断规则为两个变量是否指向同一个堆空间数据(对象)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Test { }

internal class Program
{
static void Main(string[] args)
{
Console.WriteLine(object.Equals(1, 1));

Test t = new Test();
Test t2 = t;
Console.WriteLine(object.Equals(t, t2)); //t和t2指向同一个堆空间的数据,因此是true
t2 = new Test();
Console.WriteLine(object.Equals(t, t2)); //t和t2指向不同的堆空间的数据,因此是false
}
}

输出:

1
2
3
True
True
False

ReferenceEquals

静态方法 ReferenceEquals
比较两个对象是否是相同的引用,主要是用来比较引用类型的对象
值类型对象返回值始终是 false

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Test { }

internal class Program
{
static void Main(string[] args)
{
Console.WriteLine(object.ReferenceEquals(1, 1));
Test t = new Test();
Test t2 = t;
Console.WriteLine(object.ReferenceEquals(t, t2));
t2 = new Test();
Console.WriteLine(object.ReferenceEquals(t, t2));
}
}

输出:

1
2
3
False
True
False

object中的成员方法

GetType

该方法在反射(#TODO#​)相关知识点中是非常主要的方法,之后会具体的讲解这里返回的 Type​ 类型
该方法的主要作用就是获取对象运行时的类型 Type​,通过 Type​ 结合反射相关知识点可以做很多关于对象的操作

1
2
3
4
5
6
7
8
9
10
class Test { }

internal class Program
{
static void Main(string[] args)
{
Test t3 = new Test();
Type type = t.GetType();
}
}

MemberwiseClone

MemberwiseClone​ 是一个 protected​ 方法,也就是说只能在类及其子类的内部使用,
如果想要外部使用需要声明一个 public​ 方法中调用,外部再调用这个

该方法用于获取对象的浅拷贝对象,它会返回一个新的对象,
但是 新对象中的引用变量成员 会和 老对象的引用变量成员 一致
也就是说,两个对象的引用类型成员都指向同一个数据
这意味着,修改新对象的值类型的值,不会改变老对象的值类型的值
而修改新对象的引用类型的值,会一并改变老对象引用类型的值

浅拷贝意味着虽然是两个对象,但是其成员仍然共用一个引用类型的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Test
{
public int i = 1;
public TestTwo tt = new TestTwo();

public Test PublicMemberwiseClone()
{
//相当于返回一个克隆体,转换为test类
return MemberwiseClone() as Test;
}
}

class TestTwo
{
public int i = 2;
}

internal class Program
{
static void Main(string[] args)
{
Test t3 = new Test();
Test t4 = t3.PublicMemberwiseClone();
Console.WriteLine("修改浅拷贝对象前");
Console.WriteLine("t3.i = " + t3.i);
Console.WriteLine("t3.tt.i = " + t3.tt.i);
Console.WriteLine("t4.i = " + t4.i);
Console.WriteLine("t4.tt.i = " + t4.tt.i);

t4.i = 20;
t4.tt.i = 21;
Console.WriteLine("修改浅拷贝对象后");
Console.WriteLine("t3.i = " + t3.i);
Console.WriteLine("t3.tt.i = " + t3.tt.i);
Console.WriteLine("t4.i = " + t4.i);
Console.WriteLine("t4.tt.i = " + t4.tt.i);
}
}

输出:

1
2
3
4
5
6
7
8
9
10
修改浅拷贝对象前
t3.i = 1
t3.tt.i = 2
t4.i = 1
t4.tt.i = 2
修改浅拷贝对象后
t3.i = 1
t3.tt.i = 21 //可见,修改了t4的引用成员tt的数据,t3的引用成员tt也受到的影响,则说明两个对象的tt指向同一个堆内存数据
t4.i = 20
t4.tt.i = 21

object中的虚方法

Equals(成员虚方法)

默认实现还是比较两者是否为同一个引用,即相当于 ReferenceEquals​
但是微软在所有值类型的基类 System.ValueType​ 中重写了该方法,用来比较值相等
我们也可以重写该方法,定义自己的比较相等的规则

重写 Equals​ 成员方法后,将该类传入到 Object.Equals()​ 后,比较的方式会改变

1
2
3
4
5
6
7
8
class Test
{
//这就是重写equals方法
public override bool Equals(object? obj)
{
// 在这里重写逻辑
}
}

GetHashCode

该方法是获取对象的哈希码(哈希码是一种通过算法算出的,表示对象的唯一编码,不同对象哈希码有可能一样,具体值根据哈希算法决定)
我们可以通过重写该函数来自己定义对象的哈希码算法,正常情况下,我们用的极少,基本不用。

1
2
3
4
5
6
7
8
class Test
{
//这就是重写GetHashCode方法
public override int GetHashCode()
{
// 在这里重写逻辑
}
}

Tostring

该方法用于返回当前对象代表的字符串,我们可以重写它定义的我们自己的对象转字符串规则
该方法非常常用,当我们调用打印方法时,默认调用的就是对象的 Tostring​ 方法后打印出来的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
namespace lesson22
{
class TestTwo { }
}

class Test
{
//这就是重写Tostring方法
public override string ToString()
{
return "MrTang申明的字符串";
}
}

internal class Program
{
static void Main(string[] args)
{

TestTwo tt2 = new TestTwo();
Console.WriteLine(tt2);
Test t = new Test(); //重写了tostring之后的类
Console.WriteLine(t);
}
}

输出:

1
2
lesson22.TestTwo
MrTang申明的字符串