表達式和運算符
6.1 表達式
運算符是一個符號,它表示返回單個結果的操作。操作數(operand)是指作爲運算符輸入的數據元素。一個運算符會:
● 將操作數作爲輸入
● 執行某個操作
● 基於該操作返回一個值
表達式是運算符和操作數的字符串。可以作爲操作數的結構有:
● 字面量
● 常量
● 變量
● 方法調用
● 元素訪問器,如數組訪問器和索引器
● 其他表達式
6.2 字面量
字面量(literal)是源代碼中鍵入的數字或字符串,表示一個指定類型的明確的、固定的值
預定義類型有自己的字面量形式
◾ bool有兩個字面量:true 和 false
◾ 對於引用類型變量,字面量 null 表示變量沒有設置爲內存中的數據
6.2.1 整數字面量
整數字面量是最常見的字面量(一般爲十進制數字序列)
◾ 沒有小數點
◾ 帶有可選的後綴,指明整數的類型
整數類型字面量還可以寫成十六進制(hex)形式,數字必須是十六進制數(從0到F),而且字符串必須以0x
或0X
開始(數字0,字母x)
6.2.2 實數字面量
實數字面量的組成如下:
◾ 十進制數字
◾ 一個可選的小數點
◾ 一個可選的指數部分
◾ 一個可選的後綴
格式:【十進制數字
.
十進制數字
指數(e±xx)
後綴
】
實數字面量的後綴:
後綴 | 實數類型 |
---|---|
無、D、d | double |
F、f | float |
M、m | decimal |
6.2.3 字符字面量
字符字面量有兩個單引號內的字符組成,字符字面量可以是下面任意一種:單個字符、一個簡單轉義序列、一個十六進制轉義序列或一個Unicode轉義序列
◾ 字符字面量的類型是char
◾ 簡單轉義序列是一個反斜槓後面跟着單個字符
◾ 十六進制轉義序列是一個反斜槓,後面跟着一個大寫或小寫的x,後面再跟着4個十六進制數字
◾ Unicode轉義序列是一個反斜槓,後而跟着一個大寫或小寫的u,後面再跟着4個十六進制數字
重要的特殊字符
名稱 | 轉義序列 | 十六進制編碼 |
---|---|---|
空字符 | \o | 0x0000 |
警告 | \a | 0x0007 |
退格符 | \b | 0x0008 |
水平製表符 | \t | 0x0009 |
換行符 | \n | 0x000A |
重直製表符 | \v | 0x000B |
換頁符 | \f | 0x000C |
回車符 | \r | Ox000D |
雙引號 | \" | 0x0022 |
單引號 | \’ | 0x0027 |
反斜槓 | \ | 0x005C |
6.2.4 字符串字面量
字符串字面量使用雙引號標記,不同於字符字面量使用單引號
有兩種字符串字面量類型:
◾ 常規字符串字面量
◾ 逐字字符串字面量
常規字符串申字面量由雙引號內的字符序列組成。規則字符串字面量可以包含:
◾ 字符
◾ 簡單轉義序列
◾ 十六進制和Unicode轉義序列
逐字字符串字面量的書寫如同常規字符串字面量,但它以一個@字符爲前綴。逐字字符串字面量有以下重要特徵:
◾ 逐字字面量與常規字符串字面量區別在於轉義字符串不會被求值。在雙引號中間的所有內容,包括通常被認爲是轉義序列的內容,都被嚴格按字符串中列出的那樣打印
◾ 逐字字面量的唯一例外是相鄰的雙引號組,它們被解釋爲單個雙引號字符
6.3 求值順序
表達式可以由許多嵌套的子表達式構成,子表達式的求值順序可以使表達式的最終值發生差別
運算符優先級:從高到低
分類 | 運算符 |
---|---|
初級運算符 | a.x 、f(x) 、a[x] 、x++ 、x-- 、new 、typeof 、checked 、unchecked |
一級運算符 | + 、- 、! 、++x 、--x 、(T)x |
乘法 | * 、/ 、% |
加法 | + 、- |
移位 | << 、>> |
關係和類型 | < 、> 、<= 、>= 、is 、as |
相等 | == 、!= |
位與 | & |
位異 | ^ |
位異或 | | |
條件與 | && |
條件或 | || |
條件選擇 | ?: |
賦值運算符 | = 、*= 、/= 、%= 、+= 、-= 、<<= 、>>= 、&= 、^= 、|= |
6.4 簡單算術運算符
簡單算術運算符執行基本的四則運算
運算符 | 名 稱 | 描 述 |
---|---|---|
+ | 加 | 計算兩個操作數的和 |
- | 減 | 從第一個操作數中減去第二個操作數 |
* | 乘 | 求兩個操作數的乘積 |
/ | 除 | 用第二個操作數除第一個。整數除法,裁取整數部分到最近的整數 |
6.5 求餘運算符
求餘運算符(%)
用第二個操作數除第一個操作數,忽略掉商,並返回餘數
運算符 | 名 稱 | 描 述 |
---|---|---|
% | 求餘 | 用第二個操作數除第一個操作數並返回餘數 |
6.6 關係比較運算符和相等比較運算符
關係比較運算符和相等比較運算符是二元運算符,比較它們的操作數並返回bool
型值
運算符 | 名 稱 | 描 述 |
---|---|---|
< | 小於 | 如果第一個操作數小於第二個操作數,返回true,否則返回false |
> | 大於 | 如果第一個操作數大於第二個操作數,返回true,否則返回false |
<= | 小於等於 | 如果第一個操作數小於等於第二個操作數,返回true,否則返回false |
>= | 大於等於 | 如果第一個操作數大於等於第二個操作數,返回true,否則返回false |
== | 等於 | 如果第一個操作數等於第二個操作數,返回true,否則返回false |
!= | 不等於 | 如果第一個操作數不等於第二個操作數,返回true,否則返回false |
C#中數字不具有bool
意義
比較操作和相等性操作
對於大多數引用類型來說,比較它們的相等性時,將只比較它們的引用
◾ 如果引用相等,也就是說,如果它們指向內存中相同對象,那麼相等性比較爲true,否則爲false,即使內存中兩個分離的對象在所有其他方面都完全相等
◾ 這稱爲淺比較
string類型對象也是引用類型,但它的比較方式不同。比較字符串的相等性時,將比較它們的長度和內容(區分大小寫)
◾ 如果兩個字符串有相同的長度和內容(區分大小寫),那麼相等性比較返回true,即使它們佔用不同的內存區域
◾ 這稱爲深比較(deep comparison)
6.7 遞增運算符和遞減運算符
運算符 | 名 稱 | 描 述 |
---|---|---|
++ |
前置遞增++ var |
變量的值加1並保存 返回變量的新值 |
++ |
後置遞增var++ |
變量的值加1並保存 返回變量遞增之前的舊值 |
-- |
前置遞減-- var |
變量的值減1並保存 返回變量的新值 |
-- |
後置逆減var-- |
變量的值減1並保存 返回變量遞減之前的舊值 |
◾ 無論運算符使用前置形式還是後置形式,在語句執行之後,最終存放在操作數的變量中的值是相同的
◾ 唯一不同的是運算符返回給表達式的值
6.8 條件邏輯運算符
邏輯運算符用於比較或否定它們的操作數的邏輯值,並返回結果邏輯值
邏輯與(AND)和邏輯或(OR)運算符是二元左結合運算符。邏輯非(NOT)是一元運算符
運算符 | 名 稱 | 描 述 |
---|---|---|
&& |
與 | 如果兩個操作數都是true,結果爲true;否則爲false |
|| |
或 | 如果至少一個操作數是true,結果爲true;否則爲false |
! |
非 | 如果操作數是false,結果爲true;否則爲false |
6.9 邏輯運算符
按位邏輯運算符常用於設置位組(bit pattem)的方法參數
這些運算符,除按位非運算符以外,都是二元左結合運算符,按位非是一元運算符
運算符 | 名 稱 | 描 述 |
---|---|---|
& |
位與 | 產生兩個操作數的按位與。僅當兩個操作位都爲1時結果位纔是1 |
| |
位或 | 產生兩個操作數的按位或。只要任意一個操作位爲1結果位就是1 |
^ |
位異或 | 產生兩個操作數的按位異或。僅當一個而不是兩個操作數爲1時結果位爲1 |
~ |
位非 | 操作數的每個位都取反。該操作得到操作數的二進制反碼(數字的反碼是其二進制形式按位取反的結果。也就是說,每個0都變成1,每個1都變成0) |
二元按位運算符比較它的兩個操作數中每個位置的相應位,並依據邏輯操作設置返回值中的位
6.10 移位運算符
按位移位運算符向左或向右把位組移動指定數量個位置,空出的位用0或1填充
移位運算符是二元左結合運算符
運算符 | 名 稱 | 描 述 |
---|---|---|
<< |
左移 | 將位組向左移動給定數日個位置。位從左邊移出井丟失。右邊打開的位位置用0填充 |
>> |
右移 | 將位組向右移動給定數目個位置。位從右邊移出並丟失 |
6.11 賦值運算符
賦值運算符對運算符右邊的表達式求值,並用該值設置運算符左邊的變量表達式的值
賦值運算符是二元右結合運算符
運算符 | 描 述 |
---|---|
= |
簡單賦值,計算右邊表達式的值,並把返回值賦給左邊的變量或表達式 |
*= |
複合賦值,var*=expr 等價於 var = var*(expr) |
/= |
複合賦值,var/=expr 等價於 var = var/(expr) |
%= |
複合賦值,var%=expr 等價於 var = var%(expr) |
+= |
複合賦值,var+=expr 等價於 var = var+(expr) |
-= |
複合賦值,var-=expr 等價於 var = var-(expr) |
<<= |
複合賦值,var<<=expr 等價於 var = var<<(expr) |
>>= |
複合賦值,var>>=expr 等價於 var = var>>(expr) |
&= |
複合賦值,var&=expr 等價於 var = var&(expr) |
^4= |
複合賦值,var^=expr 等價於 var = var^(expr) |
|= |
複合賦值,varl= expr 等價於 var = var| (expr) |
6.12 條件運算符
條件運算符是一種強大且簡潔的方法,基於條件的結果,返回兩個值之一
條件運算符是三元運算符
運算符 | 名 稱 | 描述 |
---|---|---|
?: | 條件運算符 | 對一個表達式求值,並依據表達式是否返回true 或false ,返回兩個值之一 |
6.14 用戶定義類型轉換
可以爲自己的類和結構定義隱式轉換和顯式轉換。這允許把用戶定義類型的對象轉換成某個其他類型,反之亦然
C#提供隱式轉換和顯式轉換
■ 對於隱式轉換,當決定在特定上下文中使用特定類型時,如有必要,編譯器會自動執行轉換
■ 對於顯式轉換,編譯器只在使用顯式轉換運算符時才執行轉換
6.15 運算符重載
C#運算符被定義爲使用預定義類型作爲操作數來工作。如果面對一個用戶定義類型,運算符完全不知道如何處理它。運算符重載允許你定義C#運算符應該如何操作自定義類型的操作數
● 運算符重載只能用於類和結構
● 爲類或結構重載一個運算符x,可以聲明一個名稱爲operator x
的方法並實現它的行爲(例如:operator +
和operator -
等)
■ 一元運算符的重載方法帶一個單獨的class或struct類型的參數
■ 二元運算符的重載方法帶兩個參數,其中至少有一個必須是class或struct類型
public static LimitedInt operator-(LimitedInt x) // Unary
public static LimitedInt operator +(LimitedInt x,double y) // Binary
運算符重載的方法聲明:
■ 聲明必須同時使用static和public的修飾符
■ 運算符必須是要操作的類或結構的成員
6.15.1 運算符重載的限制
不是所有運算符都能被重載,可以重載的類型也有限制
可重載的一元運算符:
+
、-
、!
、~
、++
、--
、true
、false
可重載的二元運算符:+
、-
、*
、/
、%
、&
、|
、^
、<<
、>>
、==
、!=
、>
、<
、<=
、>=
運算符重載不能做下面的事情:
■ 創建新運算符
■ 改變運算符的語法
■ 重新定義運算符如何處理預定義類型
■ 改變運算符的優先級或結合性
6.16 typeof運算符
typeof運算符返回作爲其參數的任何類型的System.Type對象。通過這個對象,可以瞭解類型的特徵。(對任何已知類型,只有一個System.Type對象。)你不能重載typeof運算符
typeof運算符是一元運算符
運算符 | 描述 |
---|---|
typeof | 返回已知類型的System.Type對象 |
6.17 其他運算符
這裏不介紹