pp看书笔记---C#高级编程第九版 第七章 【运算符和类型强制转换】

写在前面:

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有一个隐藏类,隐藏类通过值类型包含有一模一样的属性,在用值类型初始化自己,但隐藏类是引用类型,所以在堆上,以这样的方式来隐式转换,隐藏类就是前面说到的独立的装箱对象
当拆箱时数据复制到拆箱对象上
拆装箱都是对数据的一次复制,不会影响原来的数据
隐藏类也说明了我们为什么派生类初始化基类时是隐式的,基类转派生类需要显示说明

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值