Category: C#

C#中的ReferenceEquals介绍 0

C#中的ReferenceEquals介绍

当objA和objB是同样实例的时候(或者都是null)会返回true,其他情况会返回false。和Equal不太相同的是这个方法是没有办法override的。所以,假如你想看两个object是否相同,然后又不确认equal是否被override了,那么应该就可以使用这个方法了。 不过有下面两种情况需要注意: 假如比较值类型,也就是说objA和objB都是值类型,我们需要在他们使用ReferenceEquals之前把他们装箱。也就是说,哪怕他们显示的是同样的值类型实例,RefrenceEquals也是返回false的,如下面这个例子所示: 它返回的值如下: 而装箱之后的结果就不一样了: 它的返回值如下: 当比较string的时候,假如这个string已经interned,那么就会返回true。我们来看下面的代码: 这个例子中,其实s1和s2已经是interned,所以他们其实是指向同样的reference,因此就会返回true。 我们再看下面这个例子: 这里哪怕s3,s4他们的值是相同的,但是因为没有interned,所以他们的reference是不同的,因此返回值是false而不是true。

0

C#中的GetHashCode

所谓的hash code其实主要用在一些基于hash的集合中,比如Dictionary<TKey,Tvalue>等等。一般来说,假如两个对象是相等的,那么他们的hash值也是相等的,但是反之,则不一定,也就是说两个hash值相等的对象,他们不一定相等。 需要注意的是.NET的默认的GetHashCode是不保证一定相等的,在不同的.NET版本,不同的平台上面,返回的值都有可能不同。所以,不要使用默认的这个函数来作为唯一的判断。所以,有这两点需要注意: 同样的hash值不表示他们对象是相等的。 不要把hash值保存下来,或者在不同的应用之间传递,然后使用这个值来进行判断,因为脱离了这个应用,即使同样的对象,他的hash值也是可能不同的,这和平台,进程等等都有关系。 GetHashCode可以被子类override,换句话说,假如你不override这个函数,那么就会默认使用父类(object)的GetHashCode函数。他的计算是基于对象的引用来计算的,也就是说两个对象只要他们的引用一样,那么他们默认的GetHashCode的值也是一样的。 假如你override了GetHashCode,那么你也需要同样override Equal函数的实现,反过来也是,就是说你ovverride了Equal的实现,那么你也需要override他们GetHashCode的实现,这样他们能够返回同样的值。 下面我们来看一些例子: 这是一个简单的Point的结构,我们重写了GetHashCode的方法,这样,我们就可以看到他的HashCode使用想x^y来计算的,这个可以简单保证当x,y相等的时候,他们的hashcode是相等的。 我们在main函数中调用这个函数,可以看到下面这行代码的输出就是13. 但是这里有一个最大的问题,即使(x,y)和(y,x)的hash值其实是一样的,虽然说我们一般不能保证hash值相同,对象就相同,但是我们上面的实现重复值也太多了。所以这种情况,我们一般会使用Tuple<T1,T2>来重新计算。 这时,我们在main中来带调用这两个看看: 这样一来,我们会发现调换x和y之后,他们的hash值相差还是蛮多的: 除了这种Tuple的实现,另外一种常用的方法就是使用移位法,也就是会把每一个元素通过移位附上不同的权重,一般来说我们会使用循环移位,就是超出31bit的位再加到末尾: 有了这个方法,我们就可以把上面计算hashcode的函数改成下面这样了: 这时,我们再运行上面的方法就可以得到下面的结果:

0

C#中的new修饰符

今天我们和大家介绍一下C#中的new修饰符,注意这个修饰符,不是我们创建class的new哦。 new修饰符的基本介绍 New 修饰符主要要在子类中,当他修饰一个方法或者成员时,就表示,我们在基类中也有同样名字的方法或者成员,这里我们相当于重新建了一个同名的方法或者成员。在调用的时候,也就会覆盖基类的调用。当然我们不加new这个修饰符,也是可以运行得,但是会在编译的时候报警告。我们来来看下面的代码: 这里,我们在基类中也有一个和父类同名的Invoke函数,假如我们这样写,在编译的时候就会出现下面这样的警告: 1>C:\Users\xiaya\source\repos\ToString\ToString\NewModifer.cs(20,21,20,27): warning CS0108: ‘DerivedNewModifer.Invoke()’ hides inherited member ‘NewModifer.Invoke()’. Use the new keyword if hiding was intended. 那么要消除这个警告,我们可以给Invoke函数加上new的修饰符,如下所示: 这样之后,警告就没有了。 子类同名方法的高优先级 到这里,我相信大家还是可以理解的,同名的方法覆盖基类的方法,同步的property,field等等也是可以覆盖基类同名相关内容。下面我们继续来看这个: 这里你会发现编译也会出警告,难道这里的方法也会覆盖同名的int property?是的,C#一个规则写得很清楚,同名的方法其实优先级很高,他可以覆盖对应基类的properties,fields和types。这一点要小心。 1>C:\Users\xiaya\source\repos\ToString\ToString\NewModifer.cs(25,21,25,22): warning CS0108: ‘DerivedNewModifer.x()’ hides inherited member...

0

C# 如何 override ToString方法

众所周知,在C#中所有的class和struct都会继承object类。所以,在C#中,每一个object都有一个ToString的方法,他会返回相关的string。比如我们来看一下下面这个例子: 他们的输出如下: 下面我们来看一个类,这个是一个很简单的类,他包含两个property name和Age,这里我们就overrid了ToString的函数,你可以使用任何你想要的方式来重写这个函数,只要return一个string就可以了。 调用的代码如下: 这样就可以显示下面这个输出了: ToString的Override就是这么简单,和别的overide的函数并没有太多的差别,但是他用的非常多,因为我们经常会需要打印一下log,而ToString基本就是我们打印log的首选函数,你不需要定义什么别的函数比如showPersonInfo之类的来返回一个string,只要重写ToString函数就可以了。