文章目錄
第一章 程式設計
“要想成為真正的程式員,我們需要進行一場洗禮。”
“程式 = 資料結構 + 演算法。”這樣的公式很精闢,它越過了表層直接描述了程式的本質。不僅如此,這樣幾個簡單的單詞也讓我們明白“我們應該學習什麼內容?”。人們做任何事都有一定的程式,只是沒有意識到。有些人將日常行動列成表格,這就是“編寫程式”。
本章的學習重點:
◆ 運算子分類
◆ 運算子優先順序
1.4運算子
運算式 (expression) 由運算元 (operand) 和運算子 (operator) 構成。運算式的運算子用來指示對運算元進行什麼樣的運算。常用的運算子包括 +、-、*、/ 和 %等。運算元由變數和常量構成。常量我們在後面的章節會向大家講到,這裡主要向大家介紹運算子的相關知識,希望對大家有所協助。
1.4.1運算子分類
運算子是運算式中相當重要的一部分,它指示對錶達式中的運算元進行什麼樣的運算,如+、–、*、/、%等。根據運算子操作的個數,可以把運算子分為以下3類:
一元運算子:只帶有一個運算元並使用首碼標記法(如--x)或尾碼標記法(如x++)。
二元運算子:帶有兩個運算元並且全都使用中綴標記法(如x+y)。
三元運算子:帶有3個運算元並使用中綴標記法(如 ?: 運算子)。注意:C#語言只包含一個三元運算子。
下表列出了C#常見運算子:
類別 運算子
算術運算子 + – * / %
邏輯運算子 & | ^ ~ && || !
字串串連運算子 +
增量和遞減運算子 ++ – –
移位元運算符 << >>
比較子 == != < > <= >=
賦值運算子 = += –= *= /= %= &= |= ^= <<= >>=
成員訪問運算子 .
索引運算子 []
資料類型轉換運算子 ()
條件運算子 ?:
委託串連和刪除運算子 + –
對象建立運算子 New
類型資訊運算子 sizeof (只用於不安全的代碼) is typeof as
溢出異常控制運算子 checked unchecked
間接定址運算子 * –> & (只用於不安全的程式碼) []
命名空間別名限定符 ::
空接合運算子 ??
!、++x、--x和(T)x被稱為一元運算子。其中,(T)x運算子為強制轉換運算子,它可以將一種類型轉換為另外一種類型。下面我們詳細介紹!、++x、--x和(T)x運算子以及其他運算子的使用方法。
1、++運算子
++運算子又稱為遞增運算子,它既可以放到運算元的左邊,也可以放到運算元的右邊。如果++運算子放在運算元的左邊,則稱為該運算子為首碼遞增運算子。否則,稱為尾碼遞增運算子。文法如下:
++ expression或expression++
expression表示運算元。“++ expression”運算式首先計算expression的值,然後將其值增1,並作為該運算式的結果。“expression ++”運算式首先計算expression的值,並作為該運算式的結果,然後將expression的值增1。下面我們來看一個範例:
01 using System;
02 namespace Microsoft.Example
03 {
04 public class TestIncrement
05 {
06 public static void Main(string[] args)
07 {
08 int a = 2008; //定義一個a變數
09 int b = ++a; //進行首碼增量運算,並定義一個b變數儲存結果
10 int c = a++; //進行尾碼增量運算,並定義一個c變數儲存結果
11 Console.WriteLine("a的值為:" + a); //輸出結果
12 Console.WriteLine("b的值為:" + b); //輸出結果
13 Console.WriteLine("c的值為:" + c); //輸出結果
14 }
15 }
16 }
上述代碼中,第9行“++a”運算式執行之後,a變數的值為2009,並作為該運算式的值。因此,b變數的值為等於2009。第10行“c = a++”運算式首先擷取a變數的值,並賦值給c變數,因此,c變數的值為2009。然後,再將a變數的值增1。因此,a變數的值為2010。
最後的輸出結果:
a的值為:2010
b的值為:2009
c的值為:2009
2、--運算子
--運算子又稱為遞減運算子,它既可以放到運算元的左邊,也可以放到運算元的右邊。如果--運算子放在運算元的左邊,則稱為該運算子為首碼遞減運算子。否則,稱為尾碼遞減運算子。文法如下:
-- expression或expression--
expression表示運算元。“-- expression”運算式首先計算expression的值,然後將其值減1,並作為該運算式的結果。“expression --”運算式首先計算expression的值,並作為該運算式的結果,然後將expression的值減1。下面我們來看一個範例:
01 using System;
02 namespace Microsoft.Example
03 {
04 public class TestDeduction
05 {
06 public static void Main(string[] args)
07 {
08 int a = 2008; //定義一個a變數
09 int b = --a; //進行首碼減量運算,並定義一個b變數儲存結果
10 int c = a--; //進行尾碼減量運算,並定義一個c變數儲存結果
11 Console.WriteLine("a的值為:" + a); //輸出結果
12 Console.WriteLine("b的值為:" + b); //輸出結果
13 Console.WriteLine("c的值為:" + c); //輸出結果
14 }
15 }
16 }
上述代碼中,第9行“-- a”運算式執行之後,a變數的值為2007,並作為該運算式的值。因此,b變數的值為等於2007。第10行“c = a --”運算式首先擷取a變數的值,並賦值給c變數,因此,c變數的值為2007。然後,再將a變數的值減1。因此,a變數的值為2006。
最後的輸出結果:
a的值為:2006
b的值為:2007
c的值為:2007
3、!運算子
!運算子又稱為邏輯否定運算子。如果運算元的值為true,則結果為false。如果運算元為false,則結果為true。文法如下:
! expression
expression表示運算元。只能使用布爾類型的資料,不能使用其它資料類型使用!運算子,負責編譯會出現錯誤。下面我們來看一個範例:
01 using System;
02 namespace Microsoft.Example
03 {
04 public class TestNot
05 {
06 public static void Main(string[] args)
07 {
08 bool a = true; //定義一個a變數
09 bool b = !a; //進行邏輯否定運算,並定義一個b變數儲存結果
10 Console.WriteLine("a的值為:" + a); //輸出結果
11 Console.WriteLine("b的值為:" + b); //輸出結果
12 }
13 }
14 }
上述代碼中,第9行“!a”運算式執行之後,a變數的值為false,並作為運算式的值。因此,b變數的值為等於false。
最後的輸出結果:
a的值為:True
b的值為:False
4、(T)x運算子
(T)x運算子將運算式顯式轉換為指定的類型,文法如下:
( type ) expression
type表示類型,expression表示被轉換的運算式。下面我們來看一個範例:
01 using System;
02 namespace Microsoft.Example
03 {
04 public class TestConvertTypes
05 {
06 public static void Main(string[] args)
07 {
08 object o = 2009; //定義一個o變數
09 int i = (int)o; //進行顯式轉換
10 Console.WriteLine("i的值為:" + i);
11 }
12 }
13 }
上述代碼中,第9行(int)o進行了顯示類型轉換,把o變數的值轉換為int類型。注意:對於( T )x運算式而言,不存在從x的類型到T的顯式轉換,會發生編譯錯誤的。
最後的輸出結果:
i的值為:2009
5、算術運算子
*、/、%、+和–運算子稱為算術運算子,它們分別表示乘法、除法、餘數、加法和減法運算。文法如下:
left expression operator right expression
left expression和right expression分別表示左運算元和右運算元,operator表示運算子,可以為*、/、%、+和–。下面我們來看一個範例:
01 using System;
02 namespace Microsoft.Example
03 {
04 public class TestNumber
05 {
06 public static void Main(string[] args)
07 {
08 int a = 1; //定義a變數
09 int b = 1; //定義a變數
10 int c = a + b; //進行算術運算
11 Console.WriteLine("c的值為:" + c); //輸出結果
12 }
13 }
14 }
上述代碼中,a變數的值為1,b變數的值為1,執行+運算之後,c變數的值為等於2。如果左、右運算元的類型相同,則它們的運算結果的類型和運算元的類型相同。當運算結果超出了該類型表示的範圍時,如果使用了checked運算子,則引發System.OverflowException異常。如果使用了unchecked運算子,則不引發異常,但是其結果類型範圍外的任何有效高序位都被放棄。
最後的輸出結果:
c的值為:2
對於+運算子而言,如果其一個或兩個運算元為string類型時,則+運算子執行字串串聯操作,而不是簡單的算術運算。下面我們來看一個範例:
01 using System;
02 namespace Microsoft.Example
03 {
04 public class TestString
05 {
06 public static void Main(string[] args)
07 {
08 string stra = "2008"; //定義一個stra變數
09 string strb = ".08.08"; //定義一個stra變數
10 string strc = stra + strb; //進行連接字串運算
11 Console.WriteLine(strc); //輸出結果
12 }
13 }
14 }
上述代碼中,第8行和第9行分別定義了一個字串變數stra和strb。然後我們使用+運算子進行運算,把運算結果儲存在strc中。strc變數的值為2008.08.08字串。
6、邏輯運算子
&、^和 | 運算子稱為邏輯運算子。&運算子計算兩個運算元的按位邏輯AND,| 運算子計算兩個運算元的按位邏輯OR,^ 運算子計算兩個運算元的按位邏輯XOR。文法如下:
left expression operator right expression
left expression和right expression分別表示左運算元和右運算元,operator表示運算子,可以為&、^和 |。下面我們來看一個範例:
01 using System;
02 namespace Microsoft.Example
03 {
04 public class TestLogic
05 {
06 public static void Main(string[] args)
07 {
08 bool a = true; //定義一個a變數
09 bool b = false; //定義一個a變數
10 bool c = a & b; //進行邏輯與運算
11 Console.WriteLine("c變數的值為" + c); //輸出結果
12 }
13 }
14 }
上述代碼中,第10行我們進行了邏輯運算,具體規則如下:
如果a和b均為true,則a & b的結果為true。否則,結果為false。
如果a或b為true,則a | b的結果為true。否則,結果為false。
如果a為true而b為false,或者a為false而b為true,則a ^ b的結果為true。否則,結果為false。即a和b的值不相同時,a ^ b的結果才為true。
最後的輸出結果:
c變數的值為false。
7、條件運算子
?: 運算子稱為條件運算子,它是C#語言中唯一的一個三元運算子。文法如下:
expression ? trueResult : falseResult;
該運算式首先計算條件運算式的值。如果條件運算式的值為真,則trueResult的值,並成為運算結果。否則計算falseResult,並成為運算結果。下面我們來看一個範例:
01 using System;
02 namespace Microsoft.Example
03 {
04 public class TestCondition
05 {
06 public static void Main(string[] args)
07 {
08 int a = 10; //定義一個a變數
09 int b = 2008; //定義一個b變數
10 int c = a + b > 3000 ? a : b; //進行條件運算
11 Console.WriteLine("c變數的值為" + c); //輸出結果
12 }
13 }
14 }
上述代碼中,第10行如果a + b運算式的值大於3000時,則c的值等於a的值,否則c的值等於b的值。
最後的輸出結果:
c變數的值為2008
8、條件邏輯運算子
&& 和 || 運算子稱為條件邏輯運算子。&& 運算子為邏輯與運算子,它計算左右運算元的邏輯與。|| 運算子為邏輯或運算子,它計算左右運算元的邏輯或。文法如下:
left expression operator right expression
left expression和right expression分別表示左運算元和右運算元。operator表示運算子,可以為&&和||。
樣本:使用&&運算子計算a和b兩個運算元(均為bool類型)的和,結果儲存為c變數。
bool a = true;
bool b = false;
bool c = a && b;
分析:c變數的值為false。
注意:對於a && b運算式而言,僅當a的值為true時,才計算b的值。對於a || b運算式而言,僅當a的值為false時,才計算b的值。
9、移位元運算符
<<和>>運算子被稱為移位元運算符。<<運算子表示左移位,>>運算子表示右移位。文法如下:
expression operator count;
expression表示被移位的運算式,count表示移動的位元,operator表示運算子,可以為<<和>>。
下面我們來看一個範例:
01 using System;
02 namespace Microsoft.Example
03 {
04 public class TestMove
05 {
06 public static void Main(string[] args)
07 {
08 int a = 2008; //定義一個a變數
09 int c1 = a << 2; //進行向左移位
10 int c2 = a >> 2; //進行向右移位
11 Console.WriteLine("c1變數的值為" + c1); //輸出結果
12 Console.WriteLine("c2變數的值為" + c2); //輸出結果
13 }
14 }
15 }
上述代碼中,a << count運算式將a向左移位count個位。計算方法為:放棄a中經移位後的高序位(如果保留這些高序位,則結果將超出結果類型的範圍),將其餘的位向左位移,並將空出來的低序位均設定為零。a >> count運算式將a向右移位count個位。計算方法如下:
當a為int或long類型時,放棄a的低序位,將剩餘的位向右位移。如果x非負,則將高序空位位置設定為零。如果a為負,則將其設定為1。
當a為uint或ulong類型時,放棄a的低序位,將剩餘的位向右位移,並將高序空位位置設定為零。
最後的輸出結果:
c1變數的值為8032
c2變數的值為502
10、關係和類型測試運算子
==、!=、<、>、<=、>=、is和as運算子稱為關係和類型測試運算子。文法如下:
left expression operator right expression
left expression和right expression分別表示左運算元和右運算元,operator表示運算子,可以為==、!=、<、>、<=、>=、is和 as。其中,==、!=、<、>、<=和>=運算子為比較子,它們的具體計算方法如下:
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。
注意:==、!=、<、>、<=和>=運算子的結果均為bool類型。
下面我們來看一個範例:
01 using System;
02 namespace Microsoft.Example
03 {
04 public class TestCompare
05 {
06 public static void Main(string[] args)
07 {
08 int a = 10; //定義一個a變數
09 int b = 2008; //定義一個b變數
10 bool c = (a == b); //進行比較運算,然後把結果賦予c變數
11 Console.WriteLine("c變數的值為" + c); //輸出結果
12 }
13 }
14 }
上述代碼中,第10行中使用==運算子進行比較,如果a等於b,得到的結果是true,如果a不等於b,則得到的結果是false。
最後的輸出結果:
c變數的值為False
11、is運算子
is運算子用於動態檢查對象的運行時類型是否與給定類型相容,其結果也為bool類型。對於“e is T”運算式而言(其中,e為運算式,T為類型),如果e的結果能夠隱式轉換為T類型,則該運算式的結果為true,否則為false。
下面我們來看一個範例:
1 using System;
2 namespace Microsoft.Example
3 {
4 public class TestIs
5 {
6 static void Main()
7 {
8 int a = 10; //定義一個a變數
9 bool c = a is object; //進行is運算
10 Console.WriteLine("c變數的值為" + c);
11 }
12 }
13 }
上述代碼中, 第9行我們使用is運算子,判斷a是否是object類型,我們知道,所有的類型都是繼承於object類型的,所有is運算出來的結果是true。
最後的輸出結果:
c變數的值為true。
12、as運算子
as運算子用於將一個值顯式地轉換為一個給定的參考型別。如果轉換失敗,則返回null。
下面我們來看一個範例:
1 using System;
2 namespace Microsoft.Example
3 {
4 public class TestIs
5 {
6 static void Main()
7 {
8 int a = 10; //定義一個a變數
9 object c = a as object; //進行as運算
10 Console.WriteLine("c變數的值為" + c.GetType());
11 }
12 }
13 }
上述代碼中,第9行我們進行了as運算子的運算,把a整數轉換為object類型。這裡我們需要注意到是,這裡轉換的是類型的引用,實際內容並沒有變化,我們通常稱這種行為為裝箱操作,這個我們在後面會講到。as運算子從不引發異常。對於“e as T”運算式而言,e必須是運算式,T必須是參考型別,且運算結果總是能夠歸屬於T類型。
最後的輸出結果:
c變數的值為System.Int32
13、賦值運算子
=、*=、/=、%=、+=、-=、<<=、>>=、&=、^=和|=運算子被稱為賦值運算子,它們能夠為變數、屬性、事件或索引器元素賦新值。文法如下:
left expression operator right expression
left expression和right expression分別表示左運算元和右運算元,operator表示運算子,如=、*=、/=等。
樣本:使用*=運算子計算兩個運算元(a和b,它們的值分別為10和2008)的乘積,並賦值給左運算元b。
int a = 10,b =2008;
int b *= a;
分析:b變數的值為20080。
注意:賦值運算子的左運算元必須是屬於變數、屬性訪問、索引器訪問或事件訪問類別的運算式。
=運算子稱為簡單賦值運算子,它將右運算元的值賦予左運算元給定的變數、屬性或索引器元素。op=運算子稱為複合賦值運算子,“x op= y”運算式相當於“x = x op y”運算式。
下面列出了C#中的全部簡化賦值運算子。
運算子的簡化操作 等 價 於
x++, ++x x = x + 1
x– –,– –x x = x – 1
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
為什麼用兩個例子來說明++增量和– –遞減運算子?把運算子放在運算式的前面稱為前置,把運算子放在運算式的後面稱為後置。它們的執行方式有所不同。
1.4.2運算子優先順序
當運算式包含多個操作符時,操作符的優先順序控制著操作符的計算順序。例如,運算式x+y*z按x+(y*z)計算,因為操作符*的優先順序比+高。操作符的優先順序由操作符的相關運算式的定義來確定。
下面概述了這些運算子,並將它們按優先順序以從高到低的順序列出:
基本 x.y f(x) a[x] x++ x-- new typeof checked unchecked
一元 + - ! ~ ++x --x (T)x
乘法 * / %
加法 + -
移位 << >>
關係和類型檢測 <? >? <=? >=? is? as
相等 == !=
邏輯 XOR ^
邏輯 OR |
條件 AND &&
條件 OR ||
條件 ? :
賦值 = *= /= %= += -= <<=? >>= &= ^= |=
當運算元出現在具有相同優先順序的兩個運算子之間時,運算子的執行順序:
除了賦值運算子外,所有的二元運算子都向左順序關聯,意思是從左向右執行運算。例如,x + y + z 按 (x + y) + z 計算。
賦值運算子和條件運算子 (?:) 向右順序關聯,意思是從右向左執行運算。例如,x = y = z 按 x = (y = z) 計算。
優先順序和順序關聯性都可以用括弧控制。例如,x + y * z 先將 y 乘以 z 然後將結果與 x 相加,而 (x + y) * z 先將 x 與 y 相加,然後再將結果乘以 z。
在複雜的運算式中,應避免利用運算子優先順序來產生正確的結果。使用括弧指定運算子的執行順序,可以使代碼更整潔,避免出現潛在的衝突。