在第一章裏,瞭解了ASP.NET 3.5的特性和一些基本的.NET Framework知識,不過如果要深入到ASP.NET 3.5應用程序開發,需要對開發語言有更加深入的瞭解。而在.NET平臺上,微軟主推的編程語言就是C#,本章將會從C#的語法、結構和特性來講解,以便讀者能夠深入的瞭解C#程序設計。
2.1
C#程序
C#程序有自己的程序結構。C#編程語言類似C++/Java等面向對象編程語言,同樣需要編寫類、創建對象等。但是C#依舊有與其他面向對象編程語言不同的特性,使用這些特性能夠快速的正確的編寫C#宿主語言的應用程序,如ASP.NET、WinForm等。
2.1.1 C#程序的結構
在開始學習和編寫C#代碼之前,首先應該瞭解C#編程語言的結構,下列代碼說明了C#應用程序的基本結構。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; //使用命名空間
namespace mycsharp //程序代碼命名空間
{
class Program //應用程序主類
{
static void Main(string[] args) //入口方法
{
Console.WriteLine("Hello World"); //輸出Hello World
Console.ReadKey(); //等待用戶輸入
}
}
}
其中,using關鍵字的用途是引用微軟的.NET框架中現有的類庫資源,該關鍵字出現在應用程序代碼的開頭,並使用在cs爲後綴的文件中使用。using關鍵字通常情況下會出現幾次,其目的是引用類庫中的各種資源,這些資源不僅包括代碼中的System,System.Collections.Generic,Linq,還包括其他.NET框架的資源。
System命名空間提供了構建應用程序所需的各種系統功能,例如LINQ的類庫包括了構建LINQ應用程序的各種類庫資源。.NET中提供大量的命名空間,以便開發人員能夠使用現有的類庫進行應用程序的開發。同時,在代碼中也可以看到在其中包含一個mycsharp的一個命名空間,示例代碼如namespace mycsharp。在當前程序中聲明該命名空間,可以在其他的程序中引用這個命名空間,並使用此命名空間下的類和方法。
另外,Program是一個類名。在C#或其他的任何面嚮對象語言中(如JAVA、C++)都需要編寫類,類用於創建對象。在上述代碼中,Program是一個類的名稱。
方法是用於描述類的行爲。在上述示例第9行中,static void Main是一個全局靜態方法,它指示編譯器從此處開始執行程序,相當於程序的入口,程序運行的時候會執行Main方法作爲入口。在C# Windows編程中,大部分的應用程序必須在其組成程序的其中一個類中包含Main方法。
語句就是在C#應用程序中包含的指令,通過使用分號進行分割,編譯器通過分號來區分它們。一些編程語言只允許一行放置一條語句,但是C#允許放置多個語句,也可以將一個語句拆分成多行。雖然C#編譯器支持這樣的特性,但是還是推薦使用一行放置一個語句的,這樣不僅提高了可讀性,也便於書寫。
括號“{”和“}”用來標識程序中代碼的範圍,如上述代碼中Main方法囊括了Main方法的語句,Program類囊括了類的方法,而namespace mycsharp命名空間囊括了此命名空間裏的所有類。值得注意的是,Visual Studio 2008爲開發人員在編寫程序的時候提供了諸多的智能提示,在完成一個類或一個變量時,系統會自動補全,而當鼠標放到一個大括號上的時候,編譯器會指示開發人員此括號的範圍,如圖2-1所示。
圖 2-1 外圍元素被標記
注意:在一個類內的所有方法都是獨立的方法,所以每個大括號後面都不需要分號,同樣對於命名空間裏的所有類也是一樣。
2.1.2 C# IDE的代碼設置
代碼格式也是程序設計中一個非常重要的組成環節,他可以幫助用戶組織代碼和改進代碼,也讓代碼具有可讀性。具有良好可讀性的代碼能夠讓更多的開發人員更加輕鬆的瞭解和認知代碼。按照約定的格式書寫代碼是一個非常良好的習慣,下面的代碼示例說明了應用縮進、大小寫敏感、空白區和註釋等格式的原則。
using System;
using System.Collections.Generic;
using System.Linq; //使用LINQ命名空間
using System.Text;
namespace mycsharp //聲明命名空間
{
class Program //主程序類
{
static void Main(string[] args) //靜態方法
{
Console.WriteLine("Hello World"); //這裏輸出Hello World
Console.WriteLine("按任意鍵退出.."); Console.ReadKey(); //這裏讓用戶按鍵後退出,保持等待狀態
}
}
}
1.縮進
縮進可以幫助開發人員閱讀代碼,同樣能夠給開發人員帶來層次感。讀者可以從以上代碼看出這一串代碼讓人能夠很好的分辨區域,非常方便的就能找到Main方法的代碼區域,這是因爲括號都是有層次的。
縮進讓代碼保持優雅,同一語句塊中的語句應該縮進到同一層次,這是一個非常重要的約定,因爲它直接影響到代碼的可讀性。雖然縮進不是必須的,同樣也沒有編譯器強制,但是爲了在不同人員的開發中能夠進行良好的協調,這是一個值得去遵守的約定。
2.大小寫敏感
C#是一種對大小寫敏感的編程語言。可能php等其他語言的開發人員不太適應大小寫敏感,但是在C#中,其語法規則的確是對字符串中字母的大小寫敏感的,例如“C Sharp”、“c Sharp”、“c sHaRp”都是不同的字符串,在編程中應當注意。
3.空白
C#編譯器會忽略到空白。使用空白能夠改善代碼的格式,提高代碼的可讀性。但是值得注意的是,編譯器不對引號內的任何空白做忽略,在引號內的空格作爲字符串存在。
4.註釋
在C/C++裏,編譯器支持開發人員編寫註釋,以便開發人員能夠方便的閱讀代碼。當然,在C#裏也一樣繼承了這個良好的習慣。之所以這裏說的是習慣,是因爲編寫註釋同縮進一樣,沒有人強迫要編寫註釋,但是良好的註釋習慣能夠讓代碼更加優雅和可讀,誰也不希望自己的代碼在某一天過後自己也不認識了。
註釋的寫法是以符號“/*”開始,並以符號“*/”結束,這樣能夠讓開發人員更加輕鬆的瞭解代碼的作用,同時,也可以使用符號“//”雙斜線來寫註釋,但是這樣的註釋是單行的,示例代碼如下所示。
/*
* 多行註釋
* 本例演示了在程序中寫註釋的方法
在註釋內也可以不要開頭的*號
*/
//單行註釋,一般對單個語句進行註釋
5.佈局風格
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World"); //這裏輸出Hello World
Console.WriteLine("按任意鍵退出.."); Console.ReadKey(); //這裏讓用戶按鍵後退出,保持等待狀態
}
}
從以上代碼可以看出,程序中使用了縮進、大小寫敏感,空白區和註釋等,但是這個代碼風格依舊不是最好,可以修改代碼讓代碼更加“好看”。這裏能夠將代碼進行修正,修正後的示例代碼如下所示。
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World"); //這裏輸出Hello World
Console.WriteLine("按任意鍵退出..");
Console.ReadKey(); //這裏讓用戶按鍵後退出,保持等待狀態
}
}
這種佈局風格讓開發人員感覺到耳目一新,這樣更能方便更多的開發人員閱讀源代碼。如果打開一千行或更多代碼量的源文件時,其編碼格式都是標準的風格的話,不管是誰再接手去閱讀,都能儘快上手。不僅如此,在軟件開發當中,應該規定好每個人都使用同樣的佈局風格,讓團隊能夠協調運作。
2.2 變量
在任何編程語言中,無論是傳統的面向過程還是面向對象都必須使用變量。因此,變量都有自己的數據類型,在使用變量的時候,必須使用相同的數據類型進行運算。在程序的運行中,計算中臨時存儲的數據都必須用到變量,變量的值也會放置在內存當中,由計算機運算後再保存到變量中,由此可見,變量在任何的應用程序開發中都是非常基礎也是非常重要的。同樣,在C#中也需要變量對數據進行存儲,本節將會介紹C#的基本語法、數據類型、變量、枚舉等。
2.2.1 定義
要聲明一個變量就需要爲這個變量找到一個數據類型,在C#中,數據類型由.NET Framework和C#語言來決定,表2-1列舉了一些預定義的數據類型。
表2-1 預定義數據類型
預定義類型 |
定義 |
字節數 |
byte |
0~255之間的整數 |
1 |
sbyte |
-128~127之間的整數 |
1 |
short |
-32768~32767之間的整數 |
2 |
ushort |
0~65535之間的整數 |
2 |
int |
-2147483648~2147483647之間的整數 |
4 |
uint |
0~4294967259之間的整數 |
4 |
long |
-9223372036854775808~9223372036854775807之間的整數 |
8 |
ulong |
0~18445744073709551615之間的整數 |
8 |
bool |
布爾值,true of false |
1 |
float |
單精度浮點值 |
4 |
double |
雙精度浮點值 |
8 |
decimal |
精確的十進制值,有28個有效單位 |
12 |
object |
其他所有類型的基類 |
N/A |
char |
0~65535之間的單個Unicode字符 |
2 |
string |
任意長度的Unicode字符序列 |
N/A |
一個簡單的聲明變量的代碼如下所示:
int s; //聲明整型變量
float myfloat; //聲明浮點型變量
上述代碼聲明瞭一個整型的變量s,同時也聲明瞭一個單精度浮點型變量myfloat。
2.2.2 值類型
這種類型的對象總是直接通過其值使用,不需要對它進行引用。基於值類型的變量直接包含值。並且,所有的C#局部變量都需要初始化後纔可以使用,值類型同樣如此,初始化代碼如下所示。
int s; //聲明整型變量
s = new int(); //聲明整型變量
s = 3; //初始化變量
上式等同於如下代碼。
int s; //聲明整型變量
s = 3; //初始化變量
所有的值類型均隱式的派生自System.ValueType,並且值類型不能派生出新的類。值的類型不能爲null,但是可空類型允許將null值賦給值類型,在上面的代碼中,程序通過默認的構造函數給爲變量s初始化並賦值。
2.2.3 引用類型
引用類型的變量又稱爲對象,是可存儲對實際數據的引用。常見的引用類型有class、interface、delegate、object和string。多個引用變量可以附加於一個對象,而且某些引用可以不附加於任何對象,如果聲明瞭一個引用類型的變量卻不給他賦給任何對象,那麼它的默認值就是null。相比之下,值類型的值不能爲null。
2.3 變量規則
聲明變量並不是隨意聲明的,變量的聲明有自己的規則。在C#中,應用程序包含許多關鍵字,包括int等是不能夠聲明爲變量名的,如int int是不允許的,在進行變量的聲明和定義時,需要注意變量名稱是否與現有的關鍵字重名。
2.3.1 命名規則和命名習慣
命名規則就是給變量取名的一種規則,一般來說,命名規則就是爲了讓開發人員給變量或者命名空間取個好名,不僅要好記,還要說明一些特性。在C#裏面,有常用的一些命名的習慣如下。
q Pascal大小寫形式:所有單詞的第一個字母大寫,其他字母小寫。
q Camel大小寫形式:除了第一個單詞,所有單詞的第一個字母大寫,其他字母小寫。
當然,在其他編程中,不同的開發人員可能遇到了一些不一樣的命名規則和命名習慣,但是在C#中,推薦使用常用的一些命名習慣,這樣能保證代碼的優雅性和可讀性。同時,也應該避免使用相同名稱的命名空間或與系統命名相同的變量,如以下代碼所示:
string int; //系統會提示出錯
運行上述代碼時系統會提示錯誤,因爲字符串“int”是一個關鍵字,當使用關鍵字做變量名時,編譯器會混淆該變量是變量還是關鍵字,所以系統會提示錯誤。所以,在變量聲明時應該避免變量名稱與關鍵字重名,如果變量名稱與關鍵字重名,編譯器就會報錯,C#中常用的關鍵字如表2-2所示:
表2-2 不應使用的關鍵字名稱
AddHandler |
AddressOf |
Alias |
And |
Ansi |
As |
Assembly |
Auto |
BitAnd |
BitNot |
BitOr |
BitXor |
Boolean |
ByRef |
Byte |
ByVal |
Call |
Case |
Catch |
CBool |
CByte |
CChar |
CDate |
CDec |
CDbl |
Char |
CInt |
Class |
CLng |
CObj |
Const |
CShort |
CSng |
CStr |
CType |
Date |
Decimal |
Declare |
Default |
Delegate |
Dim |
Do |
Double |
Each |
Else |
ElseIf |
End |
Enum |
Erase |
Error |
Event |
Exit |
ExternalSource |
False |
Finally |
For |
Friend |
Function |
Get |
GetType |
Goto |
Handles |
If |
Implements |
Imports |
In |
Inherits |
Integer |
Interface |
Is |
Let |
Lib |
Like |
Long |
Loop |
Me |
Mod |
Module |
MustInherit |
MustOverride |
MyClass |
Namespace |
MyBase |
New |
Next |
Not |
Nothing |
NotInheritable |
NotOverridable |
Object |
On |
Option |
Optional |
Or |
Overloads |
Overridable |
Overrides |
ParamArray |
Preserve |
Private |
Property |
Protected |
Public |
RaiseEvent |
ReadOnly |
ReDim |
Region |
REM |
RemoveHandler |
Resume |
Return |
Select |
Set |
Shadows |
Shared |
Short |
Single |
Static |
Step |
Stop |
String |
Structure |
Sub |
SyncLock |
Then |
Throw |
To |
True |
Try |
TypeOf |
Unicode |
Until |
Variant |
When |
While |
With |
WithEvents |
WriteOnly |
Xor |
eval |
extends |
instanceof |
package |
var |
注意:標識符、參數名、函數名都不需要使用縮寫。如果要使用縮寫,超過兩個字符以上的縮寫都應該使用Camel大寫格式。
2.3.2 聲明並初始化變量
在程序代碼編寫中,需要大量的使用變量和讀取變量的值,所以需要聲明一個變量來表示一個值。這個變量可能描述是一個人的年齡,也可能是一輛車的顏色。在聲明瞭一個變量之後,就必須給這個變量一個值,只有在給變量值之後能夠說明這個變量被初始化。
1.語法
聲明變量的語法非常簡單,即在數據類型之後編寫變量名,如一個人的年齡(age)和一輛車的顏色(color),聲明代碼如下所示。
int age; //聲明一個叫age的整型變量,代表年齡
string color; //聲明一個叫color的字符串變量,代表顏色
上述代碼聲明瞭一個整型變量age和一個字符串型變量color,由於年齡的值不會小於0也不會大於100,所以在聲明時可以使用數字類型進行聲明。
2.初始化變量
變量在聲明後還需要初始化,例如“我年齡21歲,很年輕,我想買一輛紅色的車”,那麼就需要對相應的變量進行初始化,示例代碼如下所示。
int age; //聲明一個叫age的整型變量,代表年齡
string color; //聲明一個叫color的字符串變量,代表顏色
age = 21; //聲明始化,年齡21歲
color = "red"; //聲明始化,車的顏色爲紅色
上述代碼也可以合併爲一個步驟簡化編程開發,示例代碼如下所示。
int age=1; //聲明並初始化一個叫age的整型變量,代表年齡
string color="red"; //聲明初始化
3.賦值
在聲明瞭一個變量之後,就可以給這個變量賦值了,但是當編寫以下代碼就會出錯,示例代碼如下。
float a = 1.1; //錯誤的聲明浮點類型變量
當運行了以上代碼後會提示錯誤信息:不能隱式地將 Double 類型轉換爲“float”類型;請使用“F”後綴創建此類型。從錯誤中可以看出,將變量後綴增加一個“F”即可,示例代碼如下所示。
float a = 1.1F; //正確的聲明浮點類型變量
運行程序,程序就能夠編譯並運行了。這是因爲若無其他指定,C#編譯器將默認所有帶小數點的數字都是Double類型,如果要聲明成其他類型,可以通過後綴來指定數據類型,如表2-3將展示一些可用的後綴,並且後綴可用小寫。
表2-3 可用的後綴表
後綴 |
描述 |
U |
無符號 |
L |
長整型 |
UL |
無符號長整型 |
F |
浮點型 |
D |
雙精度浮點型 |
M |
十進制 |
L |
長整型 |
4.轉義字符
在開發過程當中,如果需要將單引號或者雙引號輸出,或將單引號等字符作爲字符串輸出,就會發現在字符串中單引號或者雙引號等字符是不能直接進行輸出呈現。爲了解決這一問題,於是引入了轉義字符,常用的轉義字符表如表2-4所示。
表2-4 轉義字符表
換碼序列 |
字符名稱 |
\’ |
單引號 |
\” |
雙引號 |
\\ |
反斜槓 |
\0 |
空字符 |
\a |
警報符 |
\b |
退格 |
\f |
換頁 |
\n |
換行 |
\r |
回車 |
\t |
水平製表符 |
\v |
垂直製表符 |
若在應用程序開發過程中,需要在程序裏的字符串中編寫一個雙引號並進行輸出,可以使用轉義字符進行輸出,示例代碼如下所示。
string str=”this is \” ”; //使用轉義字符
6.設置斷點
在Visual Studio .NET開發環境中,爲用戶提供了在開發應用程序時查看變量值的工具,只需要在查看的變量上設置斷點,以調試模式運行應用程序,就可以在調試窗口中查看變量的值。在代碼編輯窗口單機左邊的空白處可直接設置斷點。斷點以紅色圓點標識。也可以在調試菜單中單擊【切換斷點】按鈕,或使用快捷鍵【F9】鍵來設置斷點,如圖2-2所示。
圖2-2 設置斷點
按下【F5】鍵或在菜單欄中的調試菜單中單擊【啓動調試】按鈕都可以運行程序。當程序開始運行,程序從Main入口運行並直至遇到斷點,遇到斷點後程序將停止運行,如圖2-3所示。同時開發環境會高亮顯示下一條即將執行的代碼,同時調試查看窗口會顯示,並呈現變量的當前值,如圖2-4所示,。
圖2-3 運行到斷點,提示下一步執行的代碼 圖2-4 顯示當前值
在調試完成後,可以通過快捷鍵【Shift+F5】停止調試,也可以在菜單欄中的【調試】菜單裏的【停止調試】選項中停止應用程序的調試。如果需要繼續執行,可以按下【F5】鍵或在調試菜單中選擇【繼續執行到下一個斷點】選項進行執行。開發人員還可以通過使用快捷鍵【F10】,或在調試菜單中選擇【逐過程】或【逐語句】每次只執行一條語句,方便對代碼中變量變化的查看。
2.3.3 數組
數組是一個引用類型,開發人員能夠聲明數組並初始化數據進行相應的數組操作,數組是一種常用的數據存放方式。
1.數組的聲明
數組的聲明方法是在數據類型和變量名之間插入一組方括號,聲明格式如下所示。
string[] groups; //聲明數組
以上語句聲明瞭一個變量名爲groups的數組,其數據類型爲string。聲明瞭一個數組之後,並沒有爲此數組添加內容初始化,需要對數組初始化,才能使用數組。
2.數組的初始化
開發人員可以對數組進行顯式的初始化,以便能夠填充數組中的數據,初始化代碼如下所示。
string[] groups={"asp.net","c#","control","mvc","wcf","wpf","linq"}; //初始化數組
值得注意的是,與平常的邏輯不同的是,數組的開始並不是1,而是0。以上初始化了groups數組,所以groups[0]的值應該是“asp.net”而不是“c#”,相比之下,group[1]的值才應該是“c#”。
3..NET中數組的常用的屬性和方法
在.NET中,.NET框架爲開發人員提供了方便的方法來對數組進行運算,專注於邏輯處理的開發人員不需要手動實現對數組的操作。這些常用的方法如下所示。
q Length方法用來獲取數組中元素的個數。
q Reverse方法用來反轉數組中的元素,可以針對整個數組,或數組的一部分進行操作。
q Clone方法用來複制一個數組。
對於數組的操作,可以使用相應的方法進行數據的遍歷、查詢和反轉,示例代碼如下所示。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; //聲明文本命名空間
namespace myArray //主應用程序類
{
class Program
{
static void Main(string[] args)
{
string[] groups={"asp.net","c#","control","mvc","wcf","wpf","linq"}; //初始化一個數組
int count = groups.Length; //獲取數組的長度
Console.WriteLine("------------------------數組長度--------------------------");
Console.WriteLine(count.ToString()); //輸出數組的長度
Console.WriteLine("-----------------------原數組元素值--------------------------");
for (int i = 0; i < count; i++) //遍歷輸出數組元素
{
Console.WriteLine(groups[i]); //輸出數組中的元素
};
}
}
}
按F5運行後運行結果如圖2-5所示。
圖2-5 數組運行結果
從上述結果中可以看出,程序遍歷了數組並將數組的內容全部輸出。在進行數組中的內容輸出時,需要使用循環語句進行輸出數組的遍歷和輸出,循環語句的用法會在後面講解。
2.3.4 聲明並初始化字符串
字符串是計算機應用程序開發中常用的變量,在文本輸出、字符串索引、字符串排序中都需要使用字符串。
1.聲明及初始化字符串
字符串類型(string)是程序開發中最常見的數據類型,如上一小節聲明的數組中的任意一個元素都是一個字符串。由於數組也是有其數據類型的,所以聲明的數組是一個字符串型的數組。字符串的聲明方式和其他的數據類型聲明方式相同,字符串變量的值必須在“”雙引號之間,示例代碼如下所示。
string str="Hello World!"; //聲明字符串
在2.3.2中講解了轉義字符,當開發人員試圖在字符串中間輸入一些特殊符號的時候,會發現編譯器報錯,示例代碼如下所示。
string str="Hello "World!";
在Visual Studio 2008中編寫上述代碼,會發現褐色的字符串被分開了,並且編譯器報錯“常量中有換行符”,因爲字符串中的““”符號被當成是字符串的結束符號。爲了解決這個問題,就需要用到轉義字符。示例代碼如下所示。
string str="Hello \"World!"; //使用轉義字符
編譯並運行,運行結果如圖2-6所示。
圖2-6 使用轉義字符初始化字符串
在程序中的開發中,經常需要引用和打開某個文件,打開文件的操作必須要引用文件夾的地址。例如要打開我的文檔裏的內容,就必須在地址欄敲擊D:\Users\Administrator\Documents,在編寫程序的時候,“\”字符卻無法編寫在字符串中,同樣也需要轉義字符,示例代碼如下所示。
string str="D:\\Users\\Administrator\\Documents"; //使用轉義字符
編譯並運行,運行結果如圖2-7所示。
圖2-7 使用轉義字符初始化字符串
2.使用逐字符串
如果字符串初始化爲逐字符串,編譯器會嚴格的按照原有的樣式輸出,無論是轉義字符中的換行符還是製表符,都會按照原樣輸出。逐字符串的聲明只需要在雙引號前加上字符“@”即可,示例代碼如下所示。
string str=@"文件地址:D:\Users\Administrator\Documents \t"; //逐字符串
編譯並運行上述代碼,運行結果如圖2-8所示。
圖2-8 使用逐字符串
但是對於雙引號而言,逐字符串依舊無法正確進行輸出。若要使用逐字符串進行雙引號的輸出,則必須使用引號進行編寫以便正確的輸出雙引號,示例代碼如下所示。
string str=@""""; //輸出雙引號
編譯並運行,運行結果如圖2-9所示。
圖2-9 逐字符串輸出雙引號
3.字符串格式化
在字符串操作時,很多地方需要用到字符串格式化,使用Console.WriteLine方法就能夠實現字符串格式化,字符串格式化代碼如下所示。
string str = "Guojing"; //聲明字符串
Console.WriteLine("Hi! Myname is {0},I love C#",str); //字符串格式化輸出
Console.ReadKey(); //等待用戶按鍵
運行上述代碼,其結果如圖2-10所示。
圖2-10 字符串格式化
可以從運行結果看出,Console.WriteLine方法中,前一個傳遞的參數中的{0}被後一個傳遞的參數str替換。例子中的“{0}”被稱爲佔位符,用於標識一個參數,括號中的數字指定了參數的索引。同時,輸出方法也可以格式化多個字符串,示例代碼如下所示。
string str = "Guojing";
string str2 = "C#";
Console.WriteLine("Hi! Myname is {0},I love {1}",str,str2); //格式化多個字符串輸出
運行結果如圖2-11所示。
圖2-11 多個佔位符格式化字符串
2.3.5 操作字符串
在C#中,爲字符串提供了快捷和方便的操作,使用C#提供的類能夠進行字符串的比較、字符串的連接、字符串的拆分等操作,方便了開發人員進行字符串的操作。
1.比較字符串
如果需要比較字符串,有兩種方式,一種是值比較,一種是引用比較。值比較可以直接使用運算符“==”進行比較,示例代碼如下所示。
string str = "Guojing"; //聲明字符串
string str2 = "C#"; //聲明字符串
if (str == str2) //使用“==”比較字符串
{
Console.WriteLine("字符串相等"); //輸出不相等信息
}
else
{
Console.WriteLine("字符串不相等"); //輸出相等信息
}
當判斷兩個字符串是否指向同一個對象時,可以使用Compare方法判定兩個字符串是否指向同一個對象,示例代碼如下所示。
string str = "Guojing"; //聲明字符串
string str2 = "C#"; //聲明字符串
if (str.CompareTo(str2) > 0) //使用Compare比較字符串
{
Console.WriteLine("字符不串相等"); //輸出不相等信息
}
else
{
Console.WriteLine("字符串相等"); //輸出相等信息
}
編譯上述代碼並運行,其結果如圖2-12所示。
圖2-12 比較字符串
在上述代碼運行後,如果字符串不相等,則輸出“字符串不相等”字符,否則會輸出“字符串相等”。
2.連接字符串
當一個字符串被創建,對字符串的操作的方法實際上是對字符串對象的操作。其返回的也是新的字符串對象,與int等數據類型一樣,字符串也可以使用符號“+”進行連接,代碼如下所示。
string str = "Guojing is A C# "; //聲明字符串
string str2 = "Programmer"; //聲明字符串
Console.WriteLine(str+str2); //連接字符串
在上述例子中,聲明並初始化兩個字符串型變量str和str2,並輸出str+str2的結果,運行結果如圖2-13所示。
圖2-13 字符串連接
同樣的,str和str2也可以爲新的字符串賦值,代碼如下所示。
string mystr = str + str2; //連接字符串
Console.WriteLine(mystr); //輸出字符串
上述代碼運行結果同樣如圖2-13所示,這裏就不再運行演示。
注意:在上述代碼中,mystr被初始化str和str2的“和”,但是在運算過程當中,str和str2的值都沒有被改變。
3.拆分字符串
能夠連接一個字符串,同樣也可以拆分一個字符串。.NET Framework提供了若干方法供拆分字符串,示例代碼如下所示。
string str = "Guojing is A C# Programmer"; //聲明字符串
Console.WriteLine(str.IndexOf("is").ToString()); //拆分字符串
Console.ReadKey();
編譯運行後,可以看到返回的結果是8,說明is是字符串從開始第8位才找到is,若搜索不到查詢的字符串,則返回-1。當字符串拆分成子字符串之後,可以通過Split方法對字符串進行分割,代碼如下所示。
string str = "BeiJing,Shanghai,GuangZhou,WuHan,ShenYang"; //初始化字符串
string[] p = str.Split(','); //使用Split方法分割並存入數組
for (int i = 0; i < p.Length; i++) //遍歷顯示
{
Console.WriteLine(p[i]); //輸出字符串
}
上述代碼第一句聲明並初始化了一個字符串,第二句使用Split函數按照逗號來分割字符串,並存入到數組p內,然後遍歷顯示數組元素。
注意:使用Split函數的時候,通常情況下只能使用字符對字符串進行分割,所以使用的是單引號。
4.更改字符串大小寫
在.NET中,系統爲開發人員提供了將字符串更改爲大寫或小寫的方法,這兩個方法分別爲ToUpper()和ToLower()。使用該方法能夠進行字符串的大小寫轉換,示例代碼如下所示。
string str = "BeiJing,Shanghai,GuangZhou,WuHan,ShenYang"; //聲明字符串
Console.WriteLine(str.ToUpper()); //轉換成大寫
Console.WriteLine(str.ToLower()); //轉換成小寫
Console.ReadKey(); //等待用戶輸入
5.常用的字符串操作
在C#軟件開發過程,字符串是使用率最高的數據類型之一,開發人員往往需要對字符串進行大量的操作。這裏介紹一些經常使用的字符串操作如判斷字符串是否爲空,替換字符串中相應的字符等等。判斷字符串是否爲空會經常在程序中使用,以保證用戶輸入的完整性,示例代碼如下所示。
string str = "BeiJing,Shanghai,GuangZhou,WuHan,ShenYang"; //聲明字符串
if (String.IsNullOrEmpty(str)) //使用String類的靜態方法
{
Console.WriteLine("字符串爲空"); //輸出字符串爲空的信息
}
else
{
Console.WriteLine("字符串不爲空"); //輸出字符串不爲空的信息
}
當需要對字符串執行替換操作時,可以使用Replace方法進行字符串的替換,示例代碼如下所示。
string str = "BeiJing,Shanghai,GuangZhou,WuHan,ShenYang"; //聲明字符串
str = str.Replace("ShenYang", "ShanXi"); //使用Replace方法
Console.WriteLine(str); //輸出字符串
大多數應用程序都是對字符串進行操作,這裏簡單的介紹幾種常用的字符串的操作,熟練掌握字符串的操作對應用程序開發有很大的好處。
2.3.6 創建和使用常量
常量是一般在程序開發當中不經常更改的變量,如π值、稅率或者是數組的長度等。使用常量一般能夠讓代碼更具可讀性、更加健壯、便於維護。在程序開發當中,好的常量使用技巧對程序開發和維護都有好的影響,示例代碼如下所示。
const double pi=3.1415926; //常量pi,π
static void Main(string[] args) //程序入口方法
{
double r=2; //聲明double類型常量
double round = 2 * pi * r * r; //使用常量
Console.WriteLine(round.ToString()); //輸出變量值
Console.ReadKey(); //等待用戶輸入
}
上述代碼非常簡單,就是計算一個圓的圓周率。當代碼非常長的時候,程序也會非常幹練,容易閱讀,如果在程序中出現了以下代碼,也能夠理解該表達式的作用。示例代碼如以下所示。
double Perimeter = 2 * pi * r; //使用常量
就算是其他的開發人員閱讀到上述代碼,也能夠輕易的瞭解該語句的作用就是求圓的周長,因爲在前面定義了常量pi=3.1415926;當程序中用到這個變量的時候,立刻就能夠知道程序的作用。聲明變量的方法,只需要在普通的變量格式前加上const關鍵字即可,聲明代碼如下所示。
const double pi=3.1415926; //聲明const變量
const int max = 500; //聲明const變量
const long kilometer = 1000; //聲明const變量
使用const聲明的變量能夠在程序中使用,但是值得注意的是,使用const聲明的變量不能夠在後面的代碼中對該變量進行重新賦值。
注意:使用const聲明的變量如果在後面的代碼中進行重新賦值或更改,則編譯器會提示錯誤。const修飾符通常用於不常更改的變量的修飾。
2.3.7 創建並使用枚舉
枚舉類型是一組已命名的常量,它是一種用戶自定義類型,開發人員可以自行創建枚舉類型,聲明枚舉變量並初始化。枚舉變量和普通的變量相比,確保了只將預定的值賦予變量,讓代碼更加容易維護。在編寫代碼的時候,允許以簡單容易辨認的名字作爲變量名,使代碼更具有可讀性。同時,如果開發人員聲明枚舉變量,Visual Studio 2008還能夠提供的智能感知功能夠讓代碼更加方便的輸入。
1.聲明及初始化枚舉
如果需要創建枚舉類型,就需要使用enum關鍵字,指定一個類型名稱,如int等,然後列舉出枚舉可以使用的值,示例代碼如下所示。
enum color {red,yellow,green,blue}; //聲明枚舉
上述代碼創建了一個color類型,然後聲明瞭這個類型的變量,並使用枚舉成員賦值,示例代碼如下所示。
class Program
{
enum color {red,yellow,green,blue}; //聲明枚舉
static void Main(string[] args) //主程序入口方法
{
Console.WriteLine(color.green); //查看枚舉成員變量green
Console.ReadKey(); //等待用戶按鍵
}
}
編譯並運行上述代碼,其輸出結果爲green,說明在程序中已經對枚舉變量中的成員初始化了。
2.使用枚舉類型
枚舉是用戶自定義類型,所以在程序中可以引用用戶的自定義類型進行自定義類型的變量的創建,示例代碼如下所示。
color mycolor = color.green; //使用枚舉類型
注意:枚舉類型的定義只能在命名空間或類內聲明,否則編譯器會報錯。
4.枚舉成員的賦值和常用類型
聲明並初始化枚舉類型,也可以對枚舉成員的值進行初始化,示例代碼如下所示。
enum color {red=1,yellow=2,green=3,blue=1}; //枚舉成員的賦值
不僅可以爲枚舉成員初始化,也可以爲枚舉成員定義基本類型,示例代碼如下所示。
enum color:int {red=1,yellow=2,green=3,blue=1}; //定義基本類型
2.3.8 類型轉換
在應用程序開發當中,很多的情況都需要對數據類型進行轉換,以保證程序的正常運行。類型轉換是數據類型和數據類型之間的轉換,在.NET中,存在着大量的類型轉換,常見的類型轉換代碼如下所示。
int i = 1; //聲明整型變量
Console.WriteLine(i); //隱式轉換輸出
在上述代碼中i是整型變量而WriteLine方法的參數是Object類型,但是WriteLine方法依舊能夠正確輸出是因爲系統將i的類型在輸出的時候轉換成了字符型。在.NET框架中,有隱式轉換和顯式轉換,隱式轉換是一種由CLR自動執行的類型轉換,如上述代碼中的,就是一種隱式的轉換(開發人員不明確指定的轉換),該轉換由CLR自動的將int類型轉換成了string型。在.NET中,CLR支持許多數據類型的隱式轉換,CLR支持的類型轉換列表如表2-5所示。
表2-5 CLR支持的轉換列表
從該類型 |
到該類型 |
sbyte |
short,int,long,float,double,decimal |
byte |
short,ushort,int,uint,long,ulong,float,double,decimal |
short |
int,long,float,double,decimal |
ushort |
int,uint,long,ulong,float,double,decimal |
int |
long,float,double,decimal |
uint |
long,ulong,float,double,decimal |
long,ulong |
float,double,decimal |
float |
double |
char |
ushort,int,uint,long,ulong,float,double,decimal |
顯式轉換是一種明確要求編譯器執行的類型轉換。在程序開發過程中,雖然很多地方能夠使用隱式轉換,但是隱式轉換有可能存在風險,顯式轉換能夠通過程序捕捉進行錯誤提示。雖然隱式也會提示錯誤,但是顯式轉換能夠讓開發人員更加清楚的瞭解代碼中存在的風險並自定義錯誤提示以保證任何風險都能夠及早避免,示例代碼如下所示。
int i = 1; //聲明整型變量i
float j = (float)i; //顯式轉換爲浮點型
上述代碼說明了顯式轉換的基本語法格式,具體語法格式如下所示。
type variable1=(cast-type)variable2;
注意:顯式的轉換可能導致數據的部分丟失,如3.1415轉換爲整型的時候會變成3。
除了隱式的轉換和顯式的轉換,還可以使用.NET中的Convert類來實現轉換,即使是兩種沒有聯繫的類型也可以實現轉換。Convert類的成員函數都是靜態方法,當調用Convert類的方法時無需創建Convert對象,當使用顯式的轉換的時候,若代碼如下所示,則編譯器會報錯。
string i = "1"; //聲明字符串變量
int j = (int)i; //顯式轉換爲整型
Console.WriteLine(j); //隱式轉換爲字符串
但是明顯的是,字符串變量i的值是有可能轉換成整型變量值1的,Convert類能夠實現轉換,示例代碼如下所示。
string i = "1"; //聲明字符串變量
int j = Convert.ToInt32(i); //顯式轉換爲整型
Console.WriteLine(j); //隱式轉換爲字符串
上述代碼編譯通過並能正常運行。Convert類提供了諸多的轉換功能,每個Toxx方法都將變量的值轉換成相應.NET簡單數據類型的值,如Int16、Int32、String等。但是值得注意的是,並不是每個變量的值都能隨意轉換,示例代碼如下所示。
string i = "haha"; //聲明字符串變量
int j = Convert.ToInt32(i); //錯誤的轉換
上述代碼中,i的值是字符串“haha”,很明顯,該字符串是無法轉換爲整型變量的。運行此代碼後系統會拋出異常提示字符串“haha”不能夠轉換成整型常量。
2.4 編寫表達式
在瞭解了C#中的數據類型、變量的聲明和初始化方式、以及類型轉換等基本知識,就需要了解如何進行表達式的編寫。表達式在C#應用程序開發中非常的重要,本節將說明如何使用運算符創建和使用表達式。
2.4.1 表達式和運算符
表達式和運算符是應用程序開發中最基本也是最重要的一個部分,表達式和運算符組成一個基本語句,語句和語句之間組成函數或變量,這些函數或變量通過某種組合形成類。
1.定義
表達式是運算符和操作符的序列。運算符是個簡明的符號,包括實際中的加減乘除,它告訴編譯器在語句中實際發生的操作,而操作數既操作執行的對象。運算符和操作數組成完整的表達式。
2.運算符類型
在大部分情況下,對運算符類型的分類都是根據運算符所使用的操作數的個數來分類的,一般可以分爲三類,這三類分別如下所示。
q 一元運算符:只使用一個操作數,如(!),自增運算符(++)等等,如i++。
q 二元運算符:使用兩個操作數,如最常用的加減法,i+j。
q 三元運算符:三元運算符只有(?:)一個。
除了按操作數個數來分以外,運算符還可以按照操作數執行的操作類型來分,如下所示。
q 關係運算符。
q 邏輯運算符。
q 算術運算符。
q 位運算符。
q 賦值運算符。
q 條件運算符。
q 類型信息運算符。
q 內存訪問運算符。
q 其他運算符。
在應用程序開發中,運算符是最基本也是最常用的,它表示着一個表達式是如何進行運算的。常用的運算符如表2-6所示。
表2-6 常用的運算符
運算符類型 |
運算符 |
元運算符 |
(x),x.y,f(x),a[x],x++,x--,new,typeof,sizeof,checked,uncheck |
一元運算符 |
+,-,~!,++x,--x,(T)x, |
算術運算符 |
+,-,*,/,% |
位運算符 |
<<,>>,&,|,^,~ |
關係運算符 |
<,>,<=,>=,is,as |
邏輯運算符 |
&,|,^ |
條件運算符 |
&&,||,? |
賦值運算符 |
=,+=,-=,*=,/=,<<=,>>=,&=,^=,|= |
正如表2-5中所示,C#編程中所需要使用到的運算符都能夠通過相應的類別進行相應的分類,但其分類的標準並不是唯一的。
3.算術運算符
程序開發中常常需要使用算術運算符,算術運算符用於創建和執行數學表達式,以實現加、減、乘、除等基本操作,示例代碼如下所示。
int a = 1; //聲明整型變量
int b = 2; //聲明整型變量
int c = a + b; //使用+運算符
int d = 1 + 2; //使用+運算符
int e = 1 + a; //使用+運算符
int f = b - a; //使用-運算符
int f = b / a; //使用/運算符
注意:當除數爲0,系統會拋出DivideByZeroException異常,在程序開發中應該避免出現邏輯錯誤,因爲編譯器不會檢查邏輯錯誤,只有在運行中才會提示相應的邏輯錯誤並拋出異常。
在算術運算符中,運算符“%”代表求餘數,示例代碼如下所示。
int a = 10; //聲明整型變量
int b = 3; //聲明整型變量
Console.WriteLine((a%b).ToString()); //求10除以3
上述代碼實現了“求10除以3”的功能,其運行結果爲1。在C#的運算符中還包括自增和自減運算符,如“++”和“--”運算符。++和--運算符是一個單操作運算符,將目的操作數自增或自減1。該運算符可以放置在變量的前面和變量的後面,都不會有任何的語法錯誤,但是放置的位置不同,實現的功能也不同,示例代碼如下所示。
int a = 10; //聲明整型變量
int a2 = 10; //聲明整型變量
int b = a++; //執行自增運算
int c = ++a2; //執行自增運算
Console.WriteLine("a is " + a); //輸出a的值
Console.WriteLine("b is " + b); //輸出b的值
Console.WriteLine("c is " + c); //輸出c的值
運行結果如圖2-14所示。
圖2-14 ++運算符
由運行結果所示,變量a、a2爲10,在使用了++運算符後,a和a2分別變爲了11,而b的賦值語句代碼中使用的爲後置自增運算符,示例代碼如下所示。
int b = a++; //b=10
當執行了上述代碼後,b的值爲10,而a會自增爲11,因爲上述代碼首先會將變量a的值賦值給b變量,賦值後再進行自增。而c的賦值語句中使用的爲前置自增運算符,示例代碼如下所示。
int c = ++a2; //c=11
當執行了上述代碼後,變量c的值爲11,是因爲在執行自增操作時,首先進行自增,再將a2變量的值賦值給c。當運算符在操作數後時,操作數會賦值給新的變量,然後再自增1,當運算符在操作數前時,操作數會先進行自增或自減,然後再賦值給新變量。
4.關係運算符
關係運算符用於創建一個表達式,該表達式用來比較兩個對象並返回布爾值。示例代碼如下所示。
string a="nihao"; //聲明字符串變量a
string b="nihao"; //聲明字符串變量b
if (a == b) //使用比較運算符
{
Console.WriteLine("相等"); //輸出比較相等信息
}
else
{
Console.WriteLine("不相等"); //輸出比較不相等信息
}
關係運算符如“>”,“<”,“>=”,“<=”等同樣是比較兩個對象並返回布爾值,示例代碼如下所示。
string a="nihao"; //聲明字符串變量a
string b="nihao"; //聲明字符串變量b
if (a == b) //比較字符串,返回布爾值
{
Console.WriteLine((a == b).ToString()); //輸入比較後的布爾值
}
else
{
Console.WriteLine((a == b).ToString()); //輸入比較後的布爾值
}
編譯並運行上述程序後,其輸出爲true。若條件不成立,即如a不等於b的變量值,則返回false。該條件所以可以直接編寫在if語句中進行條件篩選和判斷。
技巧:在使用判斷的時候,可以直接使用表達式,只要表達式的返回值是布爾型的即可,同樣也可以使用類型轉換Convert.ToBoolean方法轉換。
初學者很容易錯誤的使用關係運算符中的“==”號,因爲初學者通常會將等於運算符編寫爲“=”號,示例代碼如下所示。
if (a = b) //使用布爾值布爾值
在這裏,“=”號不等於“==”號,“=”號的意義是給一個變量賦值,而“==”號是比較兩個變量的值是否相等,如果寫成上述代碼,雖然編譯器不會報錯,但是其運行過程就不是開發人員想象的流程。
5.邏輯運算符
邏輯運算符和布爾類型組成邏輯表達式。NOT運算符“!”使用單個操作數,用於轉換布爾值,即取非,示例代碼如下所示。
bool myBool = true; //創建布爾變量
bool notTrue = !myBool; //使用邏輯運算符
與其他編程語言相似的是,C#也使用AND運算符“&&”。該運算符使用兩個操作數做與運算,當有一個操作數的布爾值爲false時,則返回false,示例代碼如下所示。
bool myBool = true; //創建布爾變量
bool notTrue = !myBool; //使用邏輯運算符取反
bool result = myBool && notTrue; //使用邏輯運算符計算
同樣,C#中也使用“||”運算符來執行OR運算,當有一個操作數的布爾值爲true時,則返回true。當使用“&&”運算符和“||”運算符時,他們是短路(short-circuit)的,這也就是說,當一個布爾值能夠由前一個或前幾個操作數決定結果,那麼就不取使用剩下的操作數繼續運算而直接返回結果,示例代碼如下所示。
bool myBool = true; //創建布爾變量
bool notTrue = !myBool; //使用邏輯運算符取反
bool result = myBool && notTrue; //使用邏輯運算符計算
bool other = true; //創建布爾變量
if (result&&other) //短路操作
{
Console.WriteLine("true"); //輸出布爾值
}
else
{
Console.WriteLine("false"); //輸出布爾值
}
從上述代碼可以看到,變量other的值爲true,而result的值爲false,那麼result&&other語句中,會直接返回false,說明條件失敗。另外,在邏輯運算符中還包括XOR異或運算符“^”,該運算符確定是否操作數是否相同,若操作數的布爾值相同,則表達式將返回false。
在C#應用程序開發中,並不支持從整型直接轉換爲布爾值,雖然在C/C++中能夠直接編寫數值進行邏輯判斷,示例代碼如下所示。
int result = 1; //使用整型
if (result) //c++的轉換
{
cout<<"true";
}
else
{
cout<<"false";
}
而上述代碼如果在C#中運行,編譯器會報錯,說明C#並不支持顯式的直接從int類型到bool類型的轉換,但是使用Convert對象的靜態方法可以實現同樣的效果,代碼如下所示。
int result = 1;
if (Convert.ToBoolean(result)) //使用Convert靜態對象
{
Console.WriteLine("true"); //輸出布爾值
}
else
{
Console.WriteLine("false"); //輸出布爾值
}
注意:在編程語言中,非0的數值都爲true,雖然C#不支持隱式的轉換int到bool類型,但是Convert.ToBoolean靜態方法提供了實現,任何非0的參數都將返回true。
6.位運算符
位運算符通常使用爲模式來操作整數類型,這些位運算符非常實用。位運算符包括“<<”、“>>”、AND、OR和XOR。左移位運算符“<<”將整型中的位左移指定位數,每一次左移,整型變量的值將乘以2,代碼如下所示。
int result = 4;
Console.WriteLine((result << 1).ToString()); //左移並輸出
運行結果爲8,操作原理如圖2-15所示。
當使用“<<”運算符時,左移操作將捨棄移出的所有位,並用0來填充移入的位。同樣,右移運算符“>>”也將操作數右移,每一次右移,整型變量的值將除以2。AND位運算符“&”通過逐位執行邏輯AND運算,從而生成新的操作數,AND運算中,兩個對應的值,若有一個值爲0,則全部爲0,原理如圖2-16所示。
圖2-15 左移 圖2-16 AND位運算
OR位運算符“|”的是用方法和原理和AND位運算符“&”基本相同,其區別在於使用的是OR運算,當有一個值爲1,則結果爲1,其原理如圖2-17所示。
XOR位運算符“^”的用法和AND位運算符類似,其區別在於當兩個值相同時,執行計算的結果爲0,否則爲1,其原理圖如2-18所示。
圖2-17 OR位運算 圖2-18 XOR位運算
取補運算符“~”將生成整型類型的補碼。如原值中的1將變爲0,而0則變爲1,原理圖如2-19所示。
圖2-19 取補位運算
7.賦值運算符
C#提供了幾種類型的賦值運算符,最常見的就是“=”運算符。C#還提供了組合運算符,如“+=”、“-=”、“*=”等。“=”運算符通常用來賦值,示例代碼如下。
int a,b,c; //聲明三個整型變量
a = b = c = 1; //使用賦值運算符
上述代碼聲明並初始化3個整型變量a、b、c並初始化值這些變量的值爲1。加法賦值運算符“+=”將加法和賦值操作組合起來,先把第一個數值的值加上第二個數值的值再存放到第一個數值的,示例代碼如下所示。
a += 1; //進行自加運算
上述代碼會將變量a的值加上1並再次賦值回a,上述代碼實現的功能和以下代碼等效。
a = a + 1; //不使用+=運算符
同樣,“-=”,“*=”,“/=”都是將第一個數值的值與第二個數值的值做操作再存放到第一個數值,同樣也支持位運算符,示例代碼如下所示。
a <<= 1; //移位運算
賦值運算符不僅支持加減乘除和位運算,同樣也支持條件運算符,示例代碼如下所示。
a &= 1; //條件運算
8.條件運算符
條件運算符“?:”需要三個操作數,示例代碼如下所示。
bool ifisTrue=true; //創建布爾值
string result = ifisTrue ? "true" : "false"; //使用三元條件運算符
Console.WriteLine(result.ToString()); //輸出布爾值
上述代碼中,使用了條件運算符“?:”,條件運算符“?:”會執行第一個條件,若條件成立,則返回“:”運算符前的一個操作數的數值,否則返回“:”運算符後的操作數的數值。上述代碼中,變量ifisTrue爲true,則返回“true”。
技巧:當記憶條件運算符的時候,“?”可以被記憶爲“條件成立嗎”,如果成立,則執行第一個,否則執行第二個,如(1>2)?1:2可以解釋成1大於2嗎,大於則返回1,不大於則返回2,這樣有助於記憶和閱讀。
2.4.2 運算符的優先級
開發人員需要經常創建表達式來執行應用程序的計算,簡單的有加減法,複雜的有矩陣、數據結構等,在創建表達式時,往往需要一個或多個運算符。在多個運算符之間的運算操作時,編譯器會按照運算符的優先級來控制表達式的運算順序,然後再計算求值。例如在生活中也常常遇到這樣的計算,如1+2*3。如果在程序開發中,編譯器優先運算“+”運算符並進行計算就會造成錯誤的結果。
1.運算順序
表達式中常用的運算符的運算順序如表2-7所示。
表2-7 運算符優先級
運算符類型 |
運算符 |
元運算符 |
X.y,f(x),a[x],x++,x--,new,typeof,checked,unchecked |
一元運算符 |
+,-,!,~,++x,--x,(T)x |
算術運算符 |
*,/,% |
位運算符 |
<<,>>,&,|,^,~ |
關係運算符 |
<,>,<=,>=,is,as |
邏輯運算符 |
&,^,| |
條件運算符 |
&&,||,? |
賦值運算符 |
=,+=,-=,*=,/=,<<=,>>=,&=,^=,|= |
當執行運算1+2*3的時候,因爲“+”運算符的優先級比“*”運算符的優先級低,則當編譯器編譯表達式並進行運算的時候,編譯器會首先執行“*”運算符的乘法操作,然後執行“+”運算符的加法操作。當需要指定運算符的優先級,可以使用圓括號來告知編譯器自定義運算符的優先級,示例代碼如下所示。
c = a + b * c; //先執行乘法
c = (a + b) * c; //先執行加法
2.左結合和右結合
所有的二元運算符都是右兩個操作數,除了賦值運算符以外其他的運算符都是左結合的,而賦值運算符是右結合,示例代碼如下所示。
a + b + c; //結合方式爲(a+b)+c
a = b = c; //結合方式爲a=(b=c)
2.5 使用條件語句
程序開發中,開發人員經常遇到選擇性的問題,如用戶是否註冊。如果用戶已經註冊則允許用戶登陸,否則就跳轉到註冊頁面。這個時候,就需要在程序中使用條件語句。if是最常用的條件語句,同時,if還包括if、if else、if else if等語句用於執行復雜的條件選擇。
2.5.1 if語句的使用方法
if語句用於判斷條件並按照相應的條件執行不同的代碼塊,if語句包括多種呈現形式,這些形式分別是if、if else、if else if。
1.聲明if語句
if語句的語法如下所示。
if(布爾值) 程序語句
當布爾值爲true,則會執行程序語句,當布爾值爲false時,程序會跳過執行的語句執行,示例代碼如下所示。
if (true) //使用if語句
{
console.writeline("ture"); //爲true的代碼塊
}
上述代碼首先會判斷if語句的條件,因爲if語句的條件爲true,所以if語句會執行大括號內的代碼,程序運行會輸出字符串true,如果將if內的條件改爲false,那麼程序將不會執行大括號內的代碼,從而不會輸出字符串true。
2.聲明if else語句
if else語句的語法如下所示。
if(布爾值) 程序語句1 else 程序語句2
同樣,當布爾值爲true,則程序執行程序語句1,但當布爾值爲false時,程序則執行程序語句2,示例代碼如下所示。
if (true) //使用if語句判斷條件
{
console.writeline("ture"); //當條件爲真時執行語句
}
else //如果條件不成立則執行
{
console.writeline("false"); //當條件爲假時執行語句
}
上述代碼中if語句的條件爲true,所以if語句會執行第一個大括號中間的代碼,而如果將true改爲false,則if語句會執行第二個大括號中的代碼。
3.聲明if else if語句
當需要進行多個條件判斷是,可以編寫if else if語句執行更多條件操作,示例代碼如下所示。
if (month == "12") //判斷month是否等於12
{
console.writeline("winter"); //輸出winter
}
else if (month == "7") //判斷month是否等於7
{
console.writeline("summer"); //輸出summer
}
else if (month == "3") //判斷month是否等於3
{
console.writeline("spring"); //輸出spring
}
else //當都不成立時執行
{
console.writeline("we don’t have this month"); //輸出默認情況
}
上述代碼會判斷相應的月份,如果月份等於12,就會執行相應的大括號中的代碼,否則會繼續進行判斷,如果判斷該月份即不是3月也不是7月,說明所有的條件都不復合,則會執行最後一段大括號中的代碼。
4.使用布爾值和布爾表達式
在if語句編寫中,if語句的條件可以使用布爾值或布爾表達式,以便能夠顯式的進行判斷,示例代碼如下所示。
if (true) //使用布爾值
{
console.writeline("ture"); //輸出ture
}
if語句的條件不僅能夠由單個布爾值或表達式組成,同樣也可以由多個表達式組成,示例代碼如下所示。
if (true||false) //使用多個布爾值
{
console.writeline("ture"); //輸出ture
}
同樣在編寫if語句的條件時,可以使用複雜的布爾表達式進行條件約束,示例代碼如下所示。
if ((a==b)&&(b==c)) //使用複雜的布爾表達式
{
console.writeline("a和b相等,b和c也相等"); //輸出相等信息
}
5.使用三元運算符
三元運算符(?:)是if else語句的縮略形式,比較後並返回布爾值,熟練使用該語句可以讓代碼變得更簡練。
2.5.2 switch選擇語句的使用
switch語句根據某個傳遞的參數的值來選擇執行的代碼。在if語句中,if語句只能測試單個條件,如果需要測試多個條件,則需要書寫冗長的代碼。而switch語句能有效的避免冗長的代碼並能測試多個條件。
1.聲明switch選擇語句
Switch語句的語法如下所示。
switch (參數的值)
{
case 參數的對應值1: 操作1; break;
case 參數的對應值2: 操作2; break;
case 參數的對應值3: 操作3; break;
}
從上述語法格式中可以看出switch的語法格式。在switch表達式之後跟一連串case標記相應的switch塊。當參數的值爲某個case對應的值的時候,switch語句就會執行對應的case的值後的操作,並以break結尾跳出switch語句。若沒有對應的參數時,可以定義default條件,執行默認代碼,示例代碼如下所示。
int x;
switch (x) //switch語句
{
case 0: Console.WriteLine("this is 0"); break; //x=0時執行
case 1: Console.WriteLine("this is 1"); break; //x=1時執行
case 2: Console.WriteLine("this is 2"); break; //x=2時執行
default:Console.WriteLine(“這是默認情況”);break;
}
在上述代碼中,當x等於0的時候,就會執行case 0的操作,就執行了Console.WriteLine("this is 0")。如果x等於1,語句就會執行case 1的操作。switch不僅能夠通過數字進行判斷,還能夠通過字符進行判斷。
2.使用break跳出語句
從上述代碼中可以看出,每一個操作後面都使用了一個break語句。在C/C++中,程序員可以被允許不寫break而貫穿整個switch語句,但是在C#中不以break結尾是錯誤的,並且編譯器不會通過。因爲C#的switch語句不支持貫穿操作,因爲C#中是希望避免在應用程序的開發中出現這樣的錯誤。
注意:在C#中,可以使用goto語句模擬,繼續執行下一個case或default。儘管在程序中可以這樣做,但是會降低代碼的可讀性,所以不推薦使用goto語句。
3.switch的執行順序
switch語句能夠對相應的條件進行判斷,示例代碼下代碼所示。
int x;
switch (x) //switch語句
{
case 0: Console.WriteLine("this is 0"); break; //x=0時執行
case 1: Console.WriteLine("this is 1"); break; //x=1時執行
case 2: Console.WriteLine("this is 2"); break; //x=2時執行
default: Console.WriteLine("no one"); break; //都不滿足時執行
}
從上述代碼中分析,整型變量x被聲明,並初始化,執行switch語句,當x的值爲0的時候,case 0之後的語句就會執行,即會執行Console.WriteLine("this is 0");執行完畢後,語句執行break跳出switch語句。當x的值等於3的,switch操作會發現在case中沒有與之相等的標記,則會執行default標記並執行默認的代碼塊。
注意:在switch語句中,default語句並不是必須的,但是編寫default是可以爲條件設置默認語句。
4.使用枚舉類型
在switch表達式中,參數的類型必須爲整型、字符型、字符串型、枚舉類型或是能夠隱式轉換爲以上類型的數據類型。在switch中常常會用到枚舉類型,示例代碼如下所示。
enum season { spring,summer,autumn,winter } //聲明枚舉類型
static void Main(string[] args)
{
season mySeason=season.summer; //初始化
switch (mySeason)
{
case season.spring: Console.WriteLine("this is spring"); break; //mySeason=spring時
case season.summer: Console.WriteLine("this is summer"); break; //mySeason=summer時
case season.autumn: Console.WriteLine("this is autumn"); break; //mySeason=autumn時
case season.winter: Console.WriteLine("this is winter"); break; //mySeason=winter時
default: Console.WriteLine("no one"); break;
}
Console.ReadKey(); //等待用戶按鍵
}
運行代碼如圖2-20所示。
圖2-20 switch中使用枚舉類型
5.組合case語句
在某些情況下,一些條件所達成的效果是相同,這就要求在switch中往往需要對多個標記使用同一語句。switch語句能夠實現多個標記使用同一語句,代碼如下所示。
switch (mySeason)
{
case season.spring:
case season.summer: Console.WriteLine("this is spring and summer"); break;//組合case
case season.autumn:
case season.winter: Console.WriteLine("this is autumn and winter"); break; //組合其他條件
default: Console.WriteLine("no one"); break; //默認case
}
2.6 使用循環語句
程序開發中,經常需要對某個代碼塊執行循環,使編譯器能夠重複執行某個代碼塊來完成計算。循環能夠減少代碼量,避免重複輸入相同的代碼行,也能夠提高應用程序的可讀性。常見的循環語句有for、while、do、for each。
2.6.1 for循環語句
for循環一般用於已知重複執行次數的循環,是程序開發中常用的循環條件之一,當for循環表達式中的條件爲true時,就會一直循環代碼塊。因爲循環的次數是在執行循環語句之前計算的,所以for循環又稱作預測式循環。當表達式中的條件爲false時,for循環會結束循環並跳出。for循環語法格式如下所示。
for(初始化表達式,條件表達式,迭代表達式)
循環語句
for循環的優點就是for循環的條件都位於同一位置,同樣,循環的條件可以使用複雜的布爾表達式表示。for循環表達式包含三個部分,即初始化表達式、條件表達式和迭代表達式。當for循環執行時,將按照以下順序執行。
q 在for循環開始時,首先運行初始化表達式。
q 初始化表達式初始化後,則判斷表達式條件。
q 若表達式條件成立,則執行循環語句。
q 循環語句執行完畢後,迭代表達式執行。
q 迭代表達式執行完畢後,再判斷表達式條件並循環。
for語句循環示意圖2-21所示。
圖2-21 for循環示意圖
開發人員能夠通過編寫for循環語句進行代碼塊的重複,示例代碼如下所示。
for (int i = 0; i < 100; i++) //循環100次
{
Console.WriteLine(i); //輸出i變量的值
}
技巧:for循環即可做增量操作也可以做減量操作,如可以寫爲for(int i=10;i>0;i--),說明for循環的結構非常靈活,同樣for循環的條件,迭代表達式也不僅僅侷限與此。
for循環還可以聲明多個變量,在初始化表達式和迭代表達式中聲明不只一個變量,示例代碼如下所示。
for (int i = 0, j = 0; (i < 100) && (j < 100); i++, j++) //多個條件循環
{
Console.WriteLine("i is" + i); //輸出i變量的值
Console.WriteLine("j is" + j); //輸出j變量的值
}
2.6.2 while循環語句
while語句同for語句一樣都可以執行循環,但是while的使用更加靈活,開發人員可以在代碼塊執行前判斷條件,也可以在代碼塊執行一次後再行判斷條件。
1.while語句的語法
while語句是除了if語句以外另一個常用語句,while語句的使用方法基本上和if語句相同,其區別就在於,if語句一般需要先知道循環次數,而while語句即便不知道循環次數也可以使用。while語句基本語法如下所示。
while(布爾值)
執行語句
while語句包括兩個部分,布爾值和執行語句,while語句執行步驟一般如下所示。
q 判斷布爾值。
q 若布爾值爲true則執行語句,否則跳過。
while語句循環示意圖如圖2-22所示。
圖2-22 while語句循環示意圖
while語句示例代碼如下所示。
x = 100; //聲明整型變量
while (x != 1) //判斷x不等於1
{
x--; //x自減操作
}
上述代碼,聲明並初始化變量x等於100,當判斷條件x!=1成立時,則執行x—操作,直到條件x!=1不成立時才跳過while循環。
2.continue關鍵字:繼續執行語句
在while語句中,可以使用continue語句來執行下一次迭代而不執行完所有的執行語句,示例代碼如下所示。
int x, y; //聲明整型變量
x = 10; //初始化x
y = 10; //初始化y
while (x != 1) //如果x不等於1
{
x--; //x自減操作
Console.WriteLine(x); //輸出x
continue; //返回循環
y--; //y自減操作(但不執行)
Console.WriteLine(y); //輸出y(但不執行)
}
上述代碼聲明瞭x,y兩個整型變量,並初始化值爲10,當x不等於1時執行while循環。在while循環語句中,當執行到continue關鍵字時則跳出並繼續執行while循環而不執行continue關鍵字後的語句,如y—語句。
2.break關鍵字:跳出循環語句
break關鍵字允許程序在while循環中跳出並終止循環,從而能夠繼續執行循環後的語句,示例代碼如下所示。
while (x != 1) //如果x不等於1
{
x--; //x自減操作
Console.WriteLine(x); //輸出x
if (x == 5) //如果x等於5
{
break; //跳出循環
}
}
上述代碼判斷x是否等於5。x如果等於5,則break語句會生效並跳出循環,繼續執行while循環語句之後的代碼。
2.6.3 do while循環語句
do while循環和while循環十分相似,區別在於do while循環會執行一次執行語句,然後再判斷while中的條件。這種循環成爲後測試循環,當程序需要執行一次語句再循環的時候,do while語句是非常實用的。do while語句語法格式如下所示。
do
{執行語句}
while(布爾值);
do while語句包含兩個部分,執行語句和布爾值。與while循環語句不同的時,執行步驟首先執行一次執行語句,具體步驟如下所示。
q 執行一次執行語句。
q 判斷布爾值。
q 若布爾值爲true,則繼續執行,否則跳出循環。
while語句循環示意圖如圖2-23所示。
圖2-23 do while語句循環示意圖
do while語句示例代碼如下所示。
int x=90; //聲明整型變量
do //首先執行一次代碼塊
{
x ++; //x自增一次
Console.WriteLine(x); //輸出x的值
}
while (x < 100); //判斷x是不是小於100
上述代碼在運行時會執行一次大括號內的代碼塊,執行完畢後纔會進行相應的條件判斷。
2.6.4 foreach循環語句
for循環語句常用的另一種用法就是對數組進行操作,C#還提供了foreach循環語句,如果想重複集合或者數組中的所有條目,使用foreach是很好的解決方案。foreach語句語法格式如下
foreach (局部變量 in 集合)
執行語句;
q for each語句執行順序如下所示。
q 集合中是否存在元素。
q 若存在,則用集合中的第一個元素初始化局部變量。
q 執行控制語句。
q 集合中是否還有剩餘元素,若存在,則將剩餘的第一個元素初始化局部變量。
q 若不存在,結束循環。
foreach循環示意圖如圖2-24所示。
圖2-24 foreach語句循環示意圖
foreach語句示例代碼如下所示。
string[] str = { "hello", "world", "nice", "to", "meet", "you" }; //定義數組變量
foreach (string s in str) //如果存在元素則執行循環
{
Console.WriteLine(s); //輸出元素
}
上述代碼聲明瞭數組str,並對str數組進行遍歷循環。運行結果如圖2-25所示。
圖 2-25 foreach語句循環示例
注意:在使用foreach語句的時候,局部變量的數據類型應該與集合或數組的數據類型相同,否則編譯器會報錯。
2.7 異常處理語句
在傳統的ASP開發過程中,要發現錯誤是非常複雜和困難的,常常錯誤發生後,很難找到錯誤的代碼行。C#爲處理程序執行期間可能出現的異常情況提供內置支持,這些異常由正常控制流之外的代碼處理。常用的異常語句包括throw,try,catch等。
2.7.1 throw異常語句
throw語句用於發出在程序執行期間出現的異常情況的信號、引發異常的是一個對象,該對象的類是從System.Exception派生的。通常throw語句與try-catch或try-final語句一起使用。示例代碼如下所示。
int x = 1; //聲明整型變量x
int y = 0; //聲明整型變量y
if (y == 0) //如果y等於0
{
throw new ArgumentException(); //拋出異常
}
Console.WriteLine("除數不能爲0"); //輸出錯誤信息
上述代碼使用throw語句引發異常並向用戶輸出了異常信息。
2.7.2 try-catch異常語句
try-catch語句由一個try和一個或多個catch子句構成,這些子句可以指定不同的異常處理應用程序。當try塊中的代碼異常,則會執行catch塊的保護代碼,在應用程序開發當中,try-catch語句能夠處理異常並返回給用戶友好的錯誤提示,示例代碼如下所示。
int x = 1; //聲明整型變量x
int y = 0; //聲明整型變量y
try //嘗試處理代碼塊
{
x = x / y; //出現異常
}
catch //捕獲異常
{
Console.WriteLine("除數不能爲空"); //拋出異常
}
上述代碼試圖用一個整型變量除以一個值爲0的整型變量,不使用try-catch捕捉異常,則系統會拋出異常跳轉到開發環境或代碼塊。使用try-catch,系統同樣會拋出異常,但是開發人員能夠通過程序捕捉異常並自定義輸出異常。同樣,它也可以接受從System.Exception派生的對象傳遞過來的參數,示例代碼如下所示。
int x = 1; //聲明整型變量
int y = 0; //聲明整型變量
try //嘗試處理代碼塊
{
x = x / y; //進行除法計算
}
catch(Exception ee) //使用Exception對象
{
Console.WriteLine("除數不能爲空,具體錯誤信息如下所示\n"); //輸出錯誤信息
Console.WriteLine(ee.ToString()); //捕獲代碼
}
運行結果如圖2-26所示。
圖2-26 try-catch語句使用示例
在運行結果中,程序詳細的輸出了異常的信息,此錯誤的信息由程序捕捉,並不會停止應用程序。
注意:try-catch能夠捕捉應用程序中的錯誤信息,但是try-catch會對程序的性能造成影響,在程序開發當中,應避免不必要的try-catch語句的出現。
2.7.3 try-finally異常語句
catch用於處理應用程序語句中出現的異常,而finally語句用於清除try塊中分配的任何資源,以及運行應用程序中任何發生異常也必須執行的代碼。finally語句經常和catch語句搭配使用,示例代碼如下所示。
int x = 1; //聲明整型變量x
int y = 0; //聲明整型變量y
try //嘗試處理代碼塊
{
x = x / y; //進行除法計算
}
finally //繼續執行程序塊
{
Console.WriteLine("系統已自動停止"); //依舊輸出錯誤信息
}
上述代碼試圖用一個整型變量除以一個值爲0的整型變量,當異常發生時,系統會拋出異常,但是finally語句也被執行。
2.7.4 try-catch-finally異常語句
try-catch-final語句能夠使應用程序更加健壯。try-finally語句依舊會拋出異常,而try-catch-finally語句能夠捕獲異常並執行finally語句中的控制語句,try-catch-finally語句結構和很靈活,示例代碼如下所示。
int x = 1; //聲明整型變量x
int y = 0; //聲明整型變量y
try //嘗試處理代碼塊
{
x = x / y; //進行除法計算
}
catch (Exception ee) //捕獲異常信息
{
Console.WriteLine("除數不能爲空,具體錯誤信息如下所示"); //拋出異常
Console.WriteLine(ee.ToString()); //輸出異常信息
}
finally //繼續執行程序塊
{
Console.WriteLine("系統已自動停止"); //繼續執行程序
}
上述代碼試圖用一個整型變量除以一個值爲0的整型變量,當異常發生時,catch捕獲並拋出異常,捕獲異常後,finally語句也被執行。運行結果如圖2-27所示。
圖2-27 try-catch-finally語句運行示例
2.8 小結
本章介紹了C#語言的基本知識,包括變量、變量規則、表達式、條件語句、循環語句以及異常處理,本章主要講解了:
q 變量:介紹了變量的概念、變量的聲明以及初始化。
q 變量規則:介紹了變量的命名、規則。
q 表達式:介紹了表達式的創建和使用方法。
q 條件語句:介紹了if、if else、if else if、switch等條件語句的使用方法。
q 循環語句:介紹了for,while、do while、foreach等循環語句的使用方法。
q 異常處理:介紹了異常以及throw、try-catch、try-finally、try-catch-finally語句的使用方法。
C#語言的特性參考了Java的技術規則,在C#中也有一個虛擬機,叫公共語言運行環境(CLR)。C#的體系結構與Windows的體系結構十分相同,因此C#很容易被開發人員使用並熟悉,能夠很快的適應開發。C#和C++也有很多的相似之處,學習C++的開發人員也能夠適應C#的學習和開發。C#比C++又有了更多的增強功能,如類型安全,事件處理,隨便帳集,代碼安全性,垃圾回收等。
C#是基於.NET體系的,也是.NET體系中的風雲人物。學好C#,讀者不僅能夠開發ASP.NET應用程序,也能夠開發WinForm、WPF、WCF等應用程序。這些應用程序的開發原理上都是相通的,所以,掌握好C#基礎是非常必要的。