写在前面:
1.介绍一些不常见但有用的运算符
2.介绍C#对象相等判断方法及解析
3.运算符重载
4.类型强制转换
不常见但有用的运算符
- checked
- 溢出检查,如果溢出,则抛出OverflowException
- unchecked
- 禁止溢出检查
- is
- 类型兼容,判断对象A的类型是否与B相同,或派生自B,返回值bool
- as
- 引用类型显示转换,可转换得到具体的对象,反之为null
- ?
- 可空类型
- int ? a = null; //合法
- bool c = a <= 4; //false,但这能说明a>4吗?
- 特别说明:当比较时有可空类型,比较结果一定是false,根据这一点就不能武断的以为对立面就是true
- 可空类型
- ??
- 空合并
- int ? a = null;
- int b = a ?? 4;//如果a为null,b是4,否则b等于a
- 特别说明:4所在位置是第二个操作数,必须是与第一个操作数类型相同或者可以转换的**
- 空合并
对象相等判定
方法种类:
- 方法一:System.Object.ReferenceEquals(静态)
- 方法二:System.Object.Equals(静态)
- 方法三:System.Object.Equals
- 方法四:==
方法使用介绍:
- 方法一:用于判断引用是否相同
- 方法二:用于判断对象值是否相同
- 方法三:用于用户重写判定方法
- 方法四:用于判断对象值是否相同
方法注意:
- 1.如果判断对象值是否相同,推荐方法二,舍弃==
- 2.方法一判断值类型对象无意义,false
- 3.方法二、方法四判断对象内容是否相同,总为false
剖析:
剖析方法注意第二点:
- 前提:有个Test类,里面有一堆属性,new两个该对象,判断相等,为何是false
- 解析:
- 1.对象中的属性是基础类型,是值类型,在栈上
- 2.当new Test的时候涉及到装箱
- 3.在装箱时会在堆上产生一个临时的,独立的装箱对象
- 4.上述会产生两个独立的装箱对象,所以判断结果是false
剖析方法注意第三点:
- 前提:使用引用判断两个4是否相等为何没意义,为何是false
- 解析:
- 1.值类型使用引用类型判断,势必先需要装箱
- 2.产生两个独立的,临时的装箱对象
类型转换
两种:
- 显示转换:int类型对象给short类型对象
- 隐式转换:int类型对象给long类型对象
为下面抛砖引玉
运算符重载
目的:
代码更直观表达
工作方式:
编译器查看给定运算符的所有重载,找到最匹配的运算符进行工作,这也是重载的工作方式
工作方式解析:
假如我重载的参数是(float a, int b),但我使用的时候传入的参数是double和int,编译器没有找到参数是double和int的,但是发现double可以转换为float且不出错,就调用参数是float和int的重载
然后编译器觉的这样可行,IL语言现将double转换为float然后进行调用
同样的,如果我们有了上述重载,传入的是float,想要得到的是double类型,IL将结果在由float转换为double
技巧:
重载的工作方式是寻找最匹配的,但是不会智能到自己改变参数的顺序来进行匹配
假如我重载为: public static void operator + (int lhs, Person rhs)……
我的调用是:Person p1 = p1 + 1;
我的调用int参数是第二个
可以在重载一个:public static void operator + (Person lhs, int rhs)
{
lhs = rhs + lhs;
}
注意
1.C#要求必须是public和static
2.左边参数命名规范是lhs,右边参数命名规范是rhs
3.有些运算符重载运行成对的重载
4.可以使用implicit和explicit进行用户自定义重载
类型强制转换
1.类之间强制转换
前提:两个类之间没有继承关系
其次使用explicit将转换的代码可以在写在两个类中
本质:使用explicit达到转换效果,例如float转换为自定义对象时是new一个新的对象使用float的值去初始化它
2.基类派生类间强制转换
基类和派生类之间呢,完全可以直接转换,例如:
Father f1 = new Father();
Father f2 = new Son();
Son s1 = (Son)f1;
Son s2 = (Son)f2;
f1转换为s1时会抛错,我们采用最好的方法是new Son(f1),即:
public Son(Father father)
{ do more}即:用父类对象去初始化子类对象,因为书中对派生类的认识就是基类添加额外信息
3.装箱拆箱间强制转换
与上面的本质相同,装箱拆箱及值类型与引用类型间的强制转换,因为值类型都派生自object,所以也转化为了基类派生类间的强制转换
本质:.Net有一个隐藏类,隐藏类通过值类型包含有一模一样的属性,在用值类型初始化自己,但隐藏类是引用类型,所以在堆上,以这样的方式来隐式转换,隐藏类就是前面说到的独立的装箱对象
当拆箱时数据复制到拆箱对象上
拆装箱都是对数据的一次复制,不会影响原来的数据
隐藏类也说明了我们为什么派生类初始化基类时是隐式的,基类转派生类需要显示说明