C#语言基础(运算符与表达式)

### 一、运算符与表达式

C#提供了大量的运算符,按需要操作数的数目来分,有一元运算符(如++)、二元运算符(如+,*)、三元运算符(如? : )。按运算功能来分,基本的运算符可以分为以下几类:

![1631424648343](C:\Users\86172\AppData\Roaming\Typora\typora-user-images\1631424648343.png)

### 二、算术运算符

算术运算符如表2.3所示,表中假设x,y是某一数值类型的变量,可以是整型也可以是浮点型。

| 运算符 | 含义 | 示      例             | 运算符 | 含义 | 示      例               |
| ------ | ---- | ---------------------- | ------ | ---- | ------------------------ |
| +      | 加   | x + y ;   x+3 ;        | %      | 取模 | x % y ; 11%3 ; 11.0 % 3; |
| -      | 减   | x – y ;   y-1   ;      | ++     | 递增 | ++x ;    x++ ;           |
| *      | 乘   | x * y ;   3*4 ;        | - -    | 递减 | - -   x ;  x-   - ;      |
| /      | 除   | x / y ; 5/2; 5.0/2.0 ; |        |      |                          |

其中:
(1)“+-*/ ”运算与一般代数意义上及其他语言的相同,需要注意的是,当“/”作用的两个操作数都是整型时,其计算结果也是整型。
例如:

```
4/2              // 结果等于2 
5/2              // 结果等于2
5/2.0            // 结果等于2.5
```

(2)“%”取模运算,即获得整数除法运算的余数,也称取余。
例如:

```
11%3         // 结果等于2
12%3          // 结果等于0
11.0%3       // 结果等于2,这与C/C++不同,在C#中,“%”也可作用于浮点类型的操作数
```

(3)“++”和“--”是一元运算符,作用的操作数必须是变量,而不能是常量或表达式。它们既可出现在操作数之前(前缀运算),也可出现于操作数之后(后缀运算)。

前缀和后缀有共同之处,也有很大区别,下面举例说明:

```
++x  先将x加1个单位,然后再将计算结果作为表达式的值
x++  先将x的值作为表达式的值,然后再将x加1个单位
```

不管是前缀还是后缀,它们操作的结果对操作数而言,都是一样的(加了1个单位),但它们出现在表达式运算中是有区别的。

例如:

```
int  x , y ;
x=5 ;  y=++x ;    //  x和y的值都等于6
x=5 ;  y=x++ ;    //  x的值是6,y的值是5
```

### 三、关系运算符

关系运算符用来比较两个操作数的值,如表 2.4 所示,假设 x,y 是某相应类型的操作数,运算结果为布尔型(true或false)。

| 运    算  符 | 操      作 | 结      果                            |
| ------------ | ---------- | ------------------------------------- |
| >            | x>y        | 如果x大于y,则为true,否则为false     |
| >=           | x>=y       | 如果x大于等于y,则为true,否则为false |
| <            | x<y        | 如果x小于y,则为true,否则为false     |
| <=           | x<=y       | 如果x小于等于y,则为true,否则为false |
| = =          | x= =y      | 如果x等于y,则为true,否则为false     |
| !=           | x!=y       | 如果x不等于y,则为true,否则为false   |

如果操作数是string类型的,则在下列两种情况下被视为两个string值相等:

① 两个值均为null。

② 两个值都是对字符串实例的非空引用,这两个字符串不仅长度相同,并且每一个对应的字符位置上的字符也相同。

例如:

```
int  x=1 ,  y=1 ;
object  b1 , b2 , b3;
string  s1="ABCD",  s2="1234" ,  s3 = "ABCD" ;
b1 = x ;  b2 = b1;  b3 = y ;
x = = y ;                      // 结果为true
b1 = =b2;                      // 结果为true
b1!=b3;                      // 结果为true
s1 = =s2;                      // 结果为false
s1 = =s3;                      // 结果为true
```

### 四、逻辑运算符

逻辑运算符是用来对两个布尔类型的操作数进行逻辑运算的,运算结果也是布尔类型,如表2.5所示。

| 运    算  符 | 含      义 | 运    算  符 | 含      义 |
| ------------ | ---------- | ------------ | ---------- |
| &            | 逻辑与     | &&           | 短路与     |
| \|           | 逻辑或     | \|\|         | 短路或     |
| ^            | 逻辑异或   | !            | 逻辑非     |

假设p、q是两个布尔操作数,表2.6给出了它们逻辑运算的真值表。

| p     | q     | p & q | p \| q | p ^ q | ! p   |
| ----- | ----- | ----- | ------ | ----- | ----- |
| true  | true  | true  | true   | false | false |
| true  | false | false | true   | true  | false |
| false | true  | false | true   | true  | true  |
| false | flase | flase | false  | false | true  |

运算符“&&”和“||”的操作结果与“&”和“|”一样,但它们的短路特征使代码的效率更高。所谓短路,就是在运算过程中,如果计算第一个操作数时,就能得知运算结果,就不会再计算第二个操作数,如图2.6所示。

![1631424910342](C:\Users\86172\AppData\Roaming\Typora\typora-user-images\1631424910342.png)

**例如:**

```
int  x , y ;
bool  z ;
x = 1 ;  y = 0 ;
z = ( x >1) & (++ y >0 )            // z的值为false,y的值为1
z = ( x >1) && (++ y >0 )          // z的值为false,y的值为0
```

### 五、位 运 算 符

位运算符如表 2.7 所示,借助它们可以完成对整型数的某一位的测试、设置,以及对一个数的位置进行移动等操作,这对许多系统级程序设计非常重要。

| 运    算  符 | 含      义 |
| ------------ | ---------- |
| &            | 按位与     |
| \|           | 按位或     |
| ^            | 按位异或   |
| ~           | 按位取反   |
| >>           | 右移       |
| <<           | 左移       |

按位与、按位或、按位异或、按位取反运算与前面逻辑运算符的与、或、异或、非的操作含义相同,只不过位运算进一步把这种操作作用到每一个二进制位上,逻辑运算的真或假值对应位运算的位的1或0值。
例如:

![1631424960361](C:\Users\86172\AppData\Roaming\Typora\typora-user-images\1631424960361.png)

在实际使用中,按位与运算通常用于将某位置0或测试某位是0还是1;按位或运算通常用于将某位置1。

例如:

```
ushort  n;
n=0x17ff ;
if ( n & 0x8000 == 0 ) 
      Console.WriteLine ("最高位第十五位为0" ) ;
else
      Console.WriteLine ("最高位第十五位为1" ) ;
n = n & 0x7ffff ;                 // n 的最高位(第15位)置0,其他位不变
n = n | 0x8000 ;                  // n 的最高位(第15位)置1,其他位不变
```

按位异或运算有一个特别的属性,假设有两个整型数x和 y,则表达式 (x ^
y) ^ y值还原为x,利用这个属性可以创建简单的加密程序。例如:

```
char ch1 = 'O' , ch2 = 'K' ;
int key = 0x1f ;
Console.WriteLine ("明文:" + ch1 + ch2 ) ;
ch1 = (char) (ch1 ^ key ) ;
ch2 = (char) (ch2 ^ key ) ;
Console.WriteLine ("密文:" + ch1 + ch2 ) ;
ch1 = (char) (ch1 ^ key ) ;
ch2 = (char) (ch2 ^ key ) ;
Console.WriteLine ("解码:" + ch1 + ch2 ) ;

```

移位运算符有两个:一个左移(<<),一个右移(>>)。

语法形式:

```
value << num_bits
value >> num_bits

```

(1)左移。将给定的value向左移动num_bits位,左边移出的位丢掉,右边空出的位填0。
例如:0x1A << 2,左移过程如图2.7(a)所示。
0x1A(十进制数 26)经过左移 2 位运算,结果值是 0x68(十进制数 104),相当于对0x1A的值乘以22。但如果左移丢掉的位含有1,那么左移之后的值可能反而会变小。
例如:0x4A << 2,左移过程如图2.7(b)所示。

![1631425032973](C:\Users\86172\AppData\Roaming\Typora\typora-user-images\1631425032973.png)

(2)右移。将给定的 value 向右移动 num_bits 位,右边移出的位丢掉,左边空出的位要根据value的情况填0或1。
若value是一个带符号数,则按符号(正数为0,负数为1)补位。
例如:0x77 >> 2,右移过程如图2.8(a)所示。0x8A >> 2,右移过程如图2.8(b)所示。
若 value 是一个无符号数,左边空出的位补0。右移运算符的作用相当于将value的值整除以 

![1631425046164](C:\Users\86172\AppData\Roaming\Typora\typora-user-images\1631425046164.png)

例如:0x8AU >> 2,右移过程如图2.9所示。

![1631425058609](C:\Users\86172\AppData\Roaming\Typora\typora-user-images\1631425058609.png)

### 六、赋值运算符

#### 1.简单赋值运算符

运算符左边的称为左值,右边的称为右值。右值是一个与左值类型兼容的表达式(exp),它可以是常量、变量或一般表达式。左值必须是一个已定义的变量或对象(obj),因为赋值运算就是将表达式的值存放到左值,因此左值必须是内存中已分配的实际物理空间。

**语法形式:**

```
var = exp
```

#### 2.复合赋值运算符

在进行如x = x +3 运算时,C#提供了一种简化方式:x +=3,这就是复合赋值运算。

语法形式:

```
var  op= exp                    // op 表示某一运算符
```

等价的意义是:

```
var = var op exp
```

除了关系运算符,一般二元运算符都可以和赋值运算符在一起构成复合赋值运算,如  表2.8所示。

| 运    算  符 | 用   法 示 例 | 等价表达式 | 运    算  符 | 用   法 示 例 | 等价表达式 |
| ------------ | ------------- | ---------- | ------------ | ------------- | ---------- |
| +=           | x += y        | x = x + y  | &=           | x &= y        | x = x & y  |
| - =          | x-   = y      | x = x-y    | \|=          | x \|= y       | x = x \| y |
| *=           | x *= y        | x = x * y  | ^=           | x ^= y        | x = x ^ y  |
| /=           | x /= y        | x = x / y  | >>=          | x >>= y       | x = x >> y |
| %=           | x %= y        | x = x % y  | <<=          | x <<= y       | x = x << y |

### 七、条件运算符

语法形式:

```
exp1 ? exp2 : exp3
```

其中,表达式exp1的运算结果必须是一个布尔类型值,表达式exp2和exp3可以是任意数据类型,但它们返回的数据类型必须一致。

首先计算exp1的值,如果其值为true,则计算exp2值,这个值就是整个表达式的结果;否则,取exp3的值作为整个表达式的结果。

例如:

```
z = x > y ? x : y ;                     // z的值就是x,y中较大的一个
z = x >=0 ? x : x ;                   // z的值就是x的绝对值
```

### 八、运算符的优先级与结合性

当操作数出现在具有相同优先级的运算符之间时,如表达式“1062”按从左到右计算的结果是2,如果按从右到左计算,结果是6。“”运算符是按从左到右的次序计算的,也就是左结合;再如表达式“x=y=2”,它在执行时是按从右到左运算的,即先将数值2赋给变量y,再将y的值赋给x,所以“=”运算符是右结合的。
在表达式中,运算符的优先级和结合性控制着运算的执行顺序,也可以用圆括号“( )”显式地标明运算顺序,如表达式(x+y)* 2。

表2.9按照优先级从高到低的顺序列出了C#运算符的优先级与结合性。

| 类      别     | 运    算  符                                         | 结    合  性 |
| -------------- | ---------------------------------------------------- | ------------ |
| 初等项         | .  ( )    [ ]  new  typeof    checked  unchecked     | 从左到右     |
| 一元后缀       | ++   -   -                                           | 从右到左     |
| 一元前缀       | ++   -   -      +    -     !   ~      (T) (表达式) | 从右到左     |
| 乘法           | *    /       %                                       | 从左到右     |
| 加法           | +   -                                                | 从左到右     |
| 移位           | <<   >>                                              | 从左到右     |
| 关系和类型检测 | <   >      <=    >=   is      as                     | 从左到右     |
| 相等           | = =    !=                                            | 从左到右     |
| 逻辑与         | &                                                    | 从左到右     |
| 逻辑异或       | ^                                                    | 从左到右     |
| 逻辑或         | \|                                                   | 从左到右     |
| 条件与         | &&                                                   | 从左到右     |
| 条件或         | \|\|                                                 | 从左到右     |
| 条件           | ? :                                                  | 从右到左     |
| 赋值           | =  *=    /=  %=  +=  - =    <<=  >>=  &=    ^=  \|=  | 从右到左     |

#### 九、表达式中的类型转换

自动转换是通过使用C#的“类型提升规则”来完成的,下面是C#的类型提升规则。

(1)一个操作数是decimal类型,另一个操作数提升为decimal,但float或double类型不能自动提升为decimal类型。

(2)一个操作数是double类型,另一个操作数提升为double类型。

(3)一个操作数是float类型,另一个操作数提升为float类型。

(4)一个操作数是 ulong类型,另一个操作数提升为 ulong类型,但带符号数,如sbyte、short、int类型或long类型不能自动提升。

(5)一个操作数是long类型,另一个操作数提升为long类型。

(6)一个操作数是uint类型,另一个操作数若是sbyte、short或int类型,那么这两个操作数都提升为long类型。

(7)一个操作数是uint类型,另一个操作数提升为uint类型。

(8)除以上情况之外,两个数值类型的操作数都提升为int类型。

从上述的自动转换规则可以看出,并不是所有数据类型都能在同一个表达式中混合使用。例如,float类型就不能自动转换为decimal类型。但是,如果使用强制类型转换仍有可能获得不兼容数据类型之间的转换。
强制类型的转换形式:

```
(类型) 表达式
```

**例如:**

```
decimal  d1, d2 ;
float  f1;
d1 = 99.999; 
f1 = 0.98;
d2 = d1 + f1 ;            // 出错,因为float类型的f1不能自动转换成decimal类型
d2 = d1 + (decimal) f1;        // 使用强制类型转换后,不再报错
```

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值