运算符和类型强制转换


1.运算符

运算符的简化操作

条件运算符:

if-else的简化操作,也称三元运算符。如果条件为真,返回一个值,为假返回另外一个值。

condition?true_value:false_value

checked和unchecked运算符:

如果把一个代码块标记为checked,CLR会执行溢出检查,如果溢出,会抛出OverflowException异常,运行以下代码会抛出异常。

byte b=;
checked
{
b++;
}
Console.WriteLine(b.ToString());

如果要禁止溢出检查,将checked改为unchecked

unchecked是默认行为,只有在需要把几行未检查的代码放在一个显式地标记为checked的大代码块中,才需要显式使用unchecked

byte b=;
unchecked
{
b++;
}
Console.WriteLine(b.ToString());

is运算符:

is运算符可以检查对象是否与特定的类型兼容。“兼容”表示对象是否该类型,或者派生自该类型

int i=;
if(i is object)
{
Console.WriteLine("i is an object");
}

as运算符:

as运算符执行引用类型的显式转换。如果转换的类型与指定的类型兼容,则转换成功,否则返回null

object o1="Some String";
object o2=; string s1=o1 as string;//s1="Some String"
string s2=o2 as string;//s2=null

sizeof运算符

使用sizeof运算符可以确定栈中值类型需要的长度(单位:字节)

Console.WriteLine(sizeof(int));

如果对复杂类型(非基本类型)使用sizeof运算符,就需要把代码放在unsafe块中

unsafe
{
Console.WriteLine(sizeof(int));
}

typeof运算符:

typeof运算符返回一个特定类型的Type对象,typeof(string)返回一个String类型的Type对象。

可空运算符?和运算符:

对于布尔类型,可以给它指定true或false值。但是要把该类型的值定义为undefined;这时候就可以使用可空类型,考虑null值和各种运算符一起使用的影响。

int? a= null;
int? b= a + ;//b=null
int? c = a * ;//c=null

空合并运算符??:

可以处理可空类型和引用类型时表示null可能的值。这个运算符放在两个操作数之间。第一个操作数必须是可空类型或引用类型。第二个操作数必须与第一个操作数类型相同,或者可以隐含地转换为第一个操作数的类型。空合并运算符的计算如下:
1.如果第一个操作数不是null,整个表达式就等于第一个操作数的值。
2.如果第一个操作数是null,整个表达式就等于第二个操作数的值。

如果a是null默认等于10;如果不是null;a就是3;

int? a = null;
int b; b = a ?? ;//b has the value 10
a = ;
b = a ?? ;//b has the value 3
运算符的优先级

3.类型的安全性

我们需要把一种类型转换为需要的另一种类型。

类型转换
byte value1 = ;
byte value2 = ;
byte total;
total = value1 + value2;
Console.WriteLine(total);

在试图编译这些代码时,会得到错误信息

Cannot implicitly convert type 'int' to 'type'

隐式转换:

只要值没有发生改变。类型转换就可以自动(隐式)进行

byte value1 = ;
byte value2 = ;
long total;
total = value1 + value2;
Console.WriteLine(total);

当2个byte类型相加时,实际上和的值已经变成long类型了,这时候不需要任何的类型强制转换。

C#支持的隐式类型转换

可空类型不能隐式的转换为非可空类型。必须通过显式转换。

不能进行显式转换的情况:

装箱和拆箱

装箱和拆箱是值类型和引用类型之间相互转换是要执行的操作。

1. 装箱在值类型向引用类型转换时发生

2. 拆箱在引用类型向值类型转换时发生

拆箱操作的执行过程和装箱操作过程正好相反,是将存储在堆上的引用类型值转换为值类型并给值类型变量。

int myIntNumber = ;
object myObject = myIntNumber;

int的基类是object类型,因为所有类型都继承自object类;子类转父类是隐式转换。父类转子类是显式转换。

object number = ;
int sum = (int)number + ;

4.比较对象的相等性

比较引用类型的相等性

RefernceEquals方法
RefernceEquals方法是一个静态方法,测试两个引用是否引用类的同一个实例。特别是两个引用是否包含内存中相同地址。方法不能重写。如果提供的两个引用是引用同一个对象实例。则返回true,否则返回false

SomeClass x, y;
x = new SomeClass();
y = new SomeClass();
bool B1 = ReferenceEquals(null, null);//true
bool B2 = ReferenceEquals(null, x);//false
bool B3 = ReferenceEquals(x, y);//true

虚拟的Equals方法

静态的Equals方法

比较运算符(==):

比较运算符只做值进行比较,不做引用比较。

比较值类型的相等性

5.运算符重载

您可以重定义或重载 C# 中内置的运算符。因此,程序员也可以使用用户自定义类型的运算符。重载运算符是具有特殊名称的函数,是通过关键字 operator 后跟运算符的符号来定义的。与其他函数一样,重载运算符有返回类型和参数列表。

例如,请看下面的函数:

public static Box operator+ (Box b, Box c)
{
Box box = new Box();
box.length = b.length + c.length;
box.breadth = b.breadth + c.breadth;
box.height = b.height + c.height;
return box;
}

上面的函数为用户自定义的类 Box 实现了加法运算符(+)。它把两个 Box 对象的属性相加,并返回相加后的 Box 对象。

运算符重载的实现

下面的程序演示了完整的实现:

using System;

namespace OperatorOvlApplication
{
class Box
{
private double length; // 长度
private double breadth; // 宽度
private double height; // 高度 public double getVolume()
{
return length * breadth * height;
}
public void setLength( double len )
{
length = len;
} public void setBreadth( double bre )
{
breadth = bre;
} public void setHeight( double hei )
{
height = hei;
}
// 重载 + 运算符来把两个 Box 对象相加
public static Box operator+ (Box b, Box c)
{
Box box = new Box();
box.length = b.length + c.length;
box.breadth = b.breadth + c.breadth;
box.height = b.height + c.height;
return box;
} } class Tester
{
static void Main(string[] args)
{
Box Box1 = new Box(); // 声明 Box1,类型为 Box
Box Box2 = new Box(); // 声明 Box2,类型为 Box
Box Box3 = new Box(); // 声明 Box3,类型为 Box
double volume = 0.0; // 体积 // Box1 详述
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0); // Box2 详述
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0); // Box1 的体积
volume = Box1.getVolume();
Console.WriteLine("Box1 的体积: {0}", volume); // Box2 的体积
volume = Box2.getVolume();
Console.WriteLine("Box2 的体积: {0}", volume); // 把两个对象相加
Box3 = Box1 + Box2; // Box3 的体积
volume = Box3.getVolume();
Console.WriteLine("Box3 的体积: {0}", volume);
Console.ReadKey();
}
}
}

当上面的代码被编译和执行时,它会产生下列结果:

Box1 的体积:
Box2 的体积:
Box3 的体积:

下表描述了 C# 中运算符重载的能力:

6.用户定义的类型强制转换

实现用户定义的类型强制转换

在这个示例中,定义一个结构Currency,包含一个正的USD($)金额,C#为次提供了decimal类型,但如果需要进行复杂的财务处理。可以编写自己的结构和类来表示相应的金额。在这样的类上实现特定的方法。

struct Currency
{
public uint Dollars;
public ushort Cents; public Currency(uint dollars, ushort cents)
{
Dollars = dollars;
Cents = cents;
} public override string ToString()
{
return string.Format("${0}.{1,-2:00}", Dollars, Cents);
} public static implicit operator float(Currency value)
{
return value.Dollars + (value.Cents / 100.05f);
}
}
static void Main(string[] args)
{ Currency balance = new UnitTestProject1.Currency(, );
float f = balance;
}

如果将float类型给balance则不能进行转换。

float f = 10.5f;
Currency balance = new UnitTestProject1.Currency(, );
balance = f;

然后我们在Currency类再添加一个方法

public static explicit operator Currency(float value)
{
uint dollbars = (uint)value;
ushort cents = (ushort)((value-dollbars)*);
return new Currency(dollbars, cents);
}

下面代码会正常运行

Currency balance = new Currency(, ); Console.WriteLine(balance);
Console.WriteLine("balance is " + balance);
Console.WriteLine("balance is(using ToString()) " + balance.ToString());
float balance2 = balance;
Console.WriteLine("After converting to float,=" + balance2);
balance = (Currency)balance2;
Console.WriteLine("After converting back to Currency,=" + balance);
Console.WriteLine("Now attempt to convert out of range value of " + "-$50.50 to aCurrency:");
checked
{
balance = (Currency)(50.50);
Console.WriteLine("Result is " + balance.ToString());
}

类之间类型强制转换:

如果某个类派生自另一个类,就不能定义两个类之间的类型强制转换。
类型强制转换必须在源数据类型或目标数类型的内部定义。

基类与派生类之间强制转换:

派生类实现了基类,基类转为派生类,这种情况是可以转换成功的

基类转派生类,这种情况是不能转换成功的。

MyBase derivedObject=new MyDerived();
MyBase baseObject=new MyBase();
MyDerived derivedCopy1=(MyDerived)derivedObject; //ok
MyDerived derivedCopy2=(MyDerived)baseObject;//Throws Exception

装箱与拆箱之间强制转换:

从基本类型到object类型是一种隐式的强制转换。因为这种强制转换是从派生类到基类的转换。

Currency balance=new Currency(,);
object baseCopy=balance;

对于基类的子类实现。由基类转换为子类。需要显示的强制转换。

object derivedObject=new Currency(,)
object baseObject=new object();
Currency derivedCopy1=(Currency)derivedObject;//ok
Currency derivedCopy2=(Currency)baseObject;//Exception
多重类型的强制转换

如果方法调用带有多个重载方法,并要给该方法传递参数。而该参数的数据类型不匹配任何重载方法,就可以迫使编译器确定使用哪些强制转换方式进行数据转换,从而决定使用哪个重载方法(并进行相应的数据转换)

C#高级编程9-第7章 运算符和类型强制转换的更多相关文章

  1. 【读书笔记】C#高级编程 第七章 运算符和类型强制转换

    (一)运算符 类别 运算符 算术运算符 + - * / % 逻辑运算符 & | ^ ~ && || ! 字符串连接运算符 + 增量和减量运算符 ++ -- 移位运算符 < ...

  2. C#高级编程 (第六版) 学习 第六章:运算符和类型强制转换

    第六章 运算符和类型强制转换 1,运算符 类别 运算符 算术运算符 + - * / % 逻辑运算符 & | ^ ~ && || ! 字符串连接运算符 + 增量和减量运算符 ++ ...

  3. C#学习笔记二 (资源托管,泛型,数组和元组,运算符和类型强制转换)

     托管和非托管资源 1.托管资源是指GC管理的内存空间,非托管资源是指文件句柄,网络连接,数据库连接等. 2.方法中临时申请的变量,被存放在栈中.栈存储非对象成员的值数据.例如在方法中有B b=new ...

  4. C#高级编程笔记 2016年10月8日运算符和类型强制转换

    1.checked和unchecked 运算符 C#提供了checked 和uncheckde 运算符.如果把一个代码块标记为checked, CLR就会执行溢出检查,如果发生溢出,就抛出overfl ...

  5. C# 运算符和类型强制转换(6) 持续更新

    C#支持的运算符 https://msdn.microsoft.com/zh-cn/library/6a71f45d(v=vs.140).aspx checked 和 unchecked ; b++; ...

  6. 读《C#高级编程》第1章问题

    读<C#高级编程>第1章 .Net机构体系笔记 网红的话:爸爸说我将来会是一个牛逼的程序员,因为我有一个梦,虽然脑壳笨但是做事情很能坚持. 本章主要是了解.Net的结构,都是一些概念,并没 ...

  7. C#高级编程9 第18章 部署

    C#高级编程9 第18章 部署 使用 XCopy 进行部署 本主题演示如何通过将应用程序文件从一台计算机复制到另一台计算机来部署应用程序. 1.将项目中生成的程序集复制到目标计算机,生成的程序集位于项 ...

  8. C#高级编程9 第17章 使用VS2013-C#特性

    C#高级编程9 第17章 使用VS2013 编辑定位到 如果默认勾选了这项,请去掉勾选,因为勾选之后解决方案的目录会根据当前文件选中. 可以设置项目并行生成数 版本控制软件设置 所有文本编辑器行号显示 ...

  9. C#高级编程9 第16章 错误和异常

    C#高级编程9 第16章 错误和异常 了解这章可以学会如何处理系统异常以及错误信息. System.Exception类是.NET运行库抛出的异常,可以继承它定义自己的异常类. try块代码包含的代码 ...

随机推荐

  1. nand flash 的oob 及坏块管理

    0.NAND的操作管理方式      NAND FLASH的管理方式:以三星FLASH为例,一片Nand flash为一个设备(device),1 (Device) = xxxx (Blocks),1 ...

  2. innobackupex 相关语法讲解【转】

    innobackupex 相关语法讲解 连接服务器 The database user used to connect to the server and its password are speci ...

  3. unity 2d 游戏优化之路 遇坑记录

    情景说明:  unity 出的Android包,在目前一些主流机型跑都没有问题,但是在 小米3 这种比较老的机器上跑,报如下错误 GLSL compilation failed, no infolog ...

  4. 入门ROS教程与视频汇总(kinetic)

    参考网址: Richard Wang    3 Shawn Chen 部分视频网址: http://v.youku.com/v_show/id_XMjUxMTc5MzE5Mg http://i.you ...

  5. sql server 约束 查找

    --1.主键约束 SELECT tab.name AS [表名], idx.name AS [主键名称], col.name AS [主键列名] FROM sys.indexes idx JOIN s ...

  6. Linux下的堆off-by-one的利用

    这篇稿子已经投到了360安全播报,http://bobao.360.cn/learning/detail/3113.html

  7. Linux下堆漏洞的利用机制

    1.保护机制 )) malloc_printerr (check_action, "corrupted double-linked list", P); 这个就是所谓的堆指针的ch ...

  8. asp.net 微信公众号源码

    需要源码,请加QQ:858-048-581 功能菜单 该源码功能十分的全面,具体介绍如下:1.菜单回复:微信自定义回复.关注时回复.默认回复.文本回复.图文回复.语音回复. 请求回复记录.LBS位置回 ...

  9. 收集Nginx的json格式日志(五)

    一.配置nginx [root@linux-node1 ~]# vim /etc/nginx/nginx.conf #修改日志格式为json格式,并创建一个nginxweb的网站目录 log_form ...

  10. 问题:SpringBoot访问不到Controller

    SpringBoot正常启动,其它配置都正常,以下是控制台打印: 解决方法: 将controller与application配置文件同层,是访问时无法扫描到相应的controller,故无法映射到相应 ...