1 操作符
表达式由操作数和操作符组成
2 算术表达式
+ - * / %
2.1 基本算术表达式
加 减 乘 除
2.2 枚举运算
加法和减法操作符可以作用于枚举类型。默认的操作是将枚举类型转换为整数类型,执行加法和减法运算后再将结果重新转换为枚举类型。如果运算结果超出了枚举定义的整数范围,枚举变量仍然有效,只不过是以整数形式来表现。
2.3 模运算
除法操作符“/”是用来求两个数的商,而模操作符“%”则用来求两个数相除的余数。模运算不仅适用于整数类型,也适用于实数类型。
模运算在数论中有着广泛的运用。一个典型的例子是伪随机数的生成。
2.4 其它
2.4.1 字符串的加法
加法操作符可用于字符串的连接。
“hello, " + "Mike" = "hello, Mike"
2.4.2 代表的加减运算
C#中的加法和减法操作符还可以作用于代表类型,这称为代表的合并和删除。代表可用于方法的封装和调用。而通过代表合并,就可以一次调用同一对象的多个方法。看一面的例子:
class DelegateOperation { static void Main() { Colleague c1 = new Colleague(); c1.m_name = "李明"; c1.m_age = 20; c1.m_Fax = "07188888888"; Colleague c2 = new Colleague(); c2.m_Fax = "0216666666"; FaxDelegate d1 = new FaxDelegate(c1.SendFax); FaxDelegate d2 = new FaxDelegate(c1.ReceiveFax); //合并代表 FaxDelegate d3 = d1 + d2; d3(c2.m_Fax, "新年快乐!"); //删除代表 d3 = d3 - d1; d3(c2.m_Fax, "收到"); } } public class Colleague:Contact { public string m_Fax; public void SendFax(string targetFax,string text) { Console.WriteLine("开始拨号 " + m_Fax + "..."); Console.WriteLine("To: " + targetFax); Console.WriteLine("连接中"); Console.WriteLine("发送"); Console.WriteLine(text); Console.WriteLine("断开连接"); Console.WriteLine(); } public void ReceiveFax(string targetFax,string text) { Console.WriteLine("接收到响应从 " + targetFax + "..."); Console.WriteLine("To:" + m_Fax); Console.WriteLine("连接中"); Console.WriteLine("接收"); Console.WriteLine(text); Console.WriteLine("断开连接"); Console.WriteLine(); } } //代表定义 delegate void FaxDelegate(string targetFax,string text); public class Contact { public string m_name; public int m_age; public string m_telephone = "Unknown"; }
通过将d1和d2合并到d3,就可以通过代表d3来一次调用收发传真的两个方法;还可以通过减法操作符删除已合并的代表。程序的输出结果为:
开始拨号 07188888888... To: 0216666666 连接中 发送 新年快乐! 断开连接 接收到响应从 0216666666... To:07188888888 连接中 接收 新年快乐! 断开连接 接收到响应从 0216666666... To:07188888888 连接中 接收 收到 断开连接 请按任意键继续. . .
此外,任何代表变量加上或减去null值仍为其本身。在进行代表删除运算时,如果作为减数的代表不在作为被减数的代表中,删除运算不会产生任何效果。
3 自增和自减表达式
++ --
4 位运算表达式
对数据按二进制位进行运算
&与、|或、^异或 ~取补 <<左移 >>右移
4.1 取补运算
取补运算的操作数限定为int、uint、long、ulong和枚举类型,且返回类型与操作数类型相同。sbyte、byte、short、ushort和char类型也可以参与运算,但运算前陷式转换为int或uint类型,返回类型也为int或uint。
取补运算将操作数的二进制每一位取反,即0变成1、1变成0。
class BitReverseOperation { static void Main() { short s1 = 10; s1 = (short)~s1; ushort s2 = 10; s2 = (ushort)~s2; Console.WriteLine(s1); Console.WriteLine(s2); int i1 = 10; i1 = ~i1; uint i2 = 10; i2 = ~i2; Console.WriteLine(i1); Console.WriteLine(i2); long l1 = 10; l1 = ~l1; ulong l2 = 10; l2 = ~l2; Console.WriteLine(l1); Console.WriteLine(l2); } }
32位整数10的二进制形式是00000000 00000000 00000000 00001010,取补后的结果为11111111 11111111 11111111 11110101。有符号时将最左边的1视为符号位,转换为整数为-11;无符号时将32位都视为有效数值,转换为整数是4294967285。对于16位的short和ushort类型,运算和返回结果的类型都是32位,进行显式类型转换时截去前16位,对应的有符号和无符号整数分别是-11和65525。对于long和ulong类型则按64位进行运算并得出结果。程序输出结果为:
-11 65525 -11 4294967285 -11 18446744073709551605 请按任意键继续. . .
取补运算作用于枚举类型时,首先将枚举类型转换为int类型,运算之后再将结果重新转换为枚举类型。和枚举加减运算一样,运算结果允许超出枚举所定义的范围。
4.2 与、或和异或运算
与、或、异或这3种操作符限定的操作数可以是整数类型中的int、uint、long、ulong,还可以是枚举和布尔类型,返回类型与操作数类型相同。枚举类型参与运算前先被转换成int类型,运算之后再重新转换为枚举类型。
与、或、异或运算对两个操作数对应二进制位进行逐位运算,若位数不等则加0补齐。
& | | | ^ |
0&0=0 | 0|0=0 | 0^0=0 |
0&1=0 | 0|1=1 | 0^1=1 |
1&0=0 | 1|0=1 | 1^0=1 |
1&1=1 | 1|1=0 | 1^1=0 |
C#中的异或,可以理解为排它性运算符。按位异或的三个特点:
--0异或任何数=任何数
--1异或任何数=任何数取反
--任何数异或自已=0
异或的用途:
--使某些特定的位翻转:使10100001的第2,3位翻转,可用该数与00000110异或
--实现相个值的交换,而不用使用临时变量:a=a^b;b=a^b;a=a^b;
--在汇编语言中通过变量异位自已将变量置0
--通过相个数异位是否为0判断两个数是否相等。
4.3 移位运算
移位运算的左操作数可以是int、uint、long、ulong整数类型,表示要移位的整数;右操作数只能是int类型,表示所移的位数。表达式返回类型与左操作数的类型相同。
1. 左移位
将操作数的二进制位依次左移,左边的高位被舍弃,右边的低位顺序补0.
2. 右移位
与左移位操作相反,并且:
--对于有符号整数,为正数则高位顺序补0,为负数则高位顺序补1;
--对于无符号整数,高位顺序补0;
由于对数据的操作方式与计算机的内部存储方式相同,位运算通常具有很高的效率,在科学计算、数据压缩、文件加密等领域得到了广泛的应用。对于整数的移位运算,在有效范围内,左移n位相当于乘以2的n次方,右移相当于除于2的n次方(舍去余数),而且运算速度远远高于乘除运算。
5 赋值表达式
= += -= *= /= %= &= |= ^= <<= >>=
6 关系表达式
== != < > <= >= is
7 条件逻辑表达式
&& || !
只能作用于布尔类型的操作数。其运算法则为:
false && false = false false && true = false ture && true = true false || false = false false || true = true true || true = true !false = true !true = false
逻辑与、或、非对布尔类型的操作数的运算效果与位运算中的与、或、取反运算效果相同,但不能把条件逻辑运算和位运算的性质相混淆。
在条件逻辑表达式的求值过程中,有时候不需要把整个表达式执行完就可以确定结果。这种情况称之为条件逻辑表达式的“短路”。
--a&&b,只有当a为true时,才继续求解表达式的值;若a为false,逻辑表达式的值已确定为false,不再考虑b的情况。
--a||b,只有当a为false时,才继续求解表达式的值;若a为true,逻辑表达式的值已经确定的true,不再考虑b的情况。
8 其它特殊表达式
8.1 一元加减表达式
int i=+2; int j=+i;
8.2 条件表达式
i==0?x:y
8.3 类型表达式
8.3.1 类型转换表达式
(T) e
8.3.2 类型获取表达式
typeof
8.3.3 类型转换检查表达式
is as
is运算返回布尔值
as运算返回转换之后的类型
8.4 创建表达式
new
8.5 溢出表达式
checked unchecked
用于控制程序是否对算术运算和类型转换时可以发出的溢出进行检查。
如果不加申明,默认对常量表达式溢出检查为checked,而对非常量表达式的溢出检查为unchecked.
使用了checked操作符的表达式,对于常量表达式,如果运算发生溢出,代码将不能通过编译,例如下面代码都是不合法的。
byte b1=(byte) 256;// 默认为checked,错误:发生溢出 byte b2=checked(255+1);//错误:发生溢出
对于非常量表达式,代码可通过编译,但执行到溢出代码时,会发生"System.OverflowException"异常,如:
byte b1=255; byte b2=checked(b1+1);//异常,发生溢出
使用了unchecked操作符的表达式,如果运算发生溢出,超出的部分将被截断,成为合法表达式。
int i1=int.MaxValue;//2147483647 int i2=unchecked(i1+1);//-2147483648