緒論
C#是這樣的一種語言,具備C++的特色,象Java同樣的編程風格, 而且象Basic同樣的快速開發模型。若是你已經知道了C++,本文會在不到一個小時的時間內讓你迅速掌握C#的語法。熟悉Java的話會更好,由於Java的程序結構、打包(Packages)和垃圾收集的概念有助於你更快的瞭解C#。所以在討論C#的構造時,我會假定你瞭解C++。
本文會討論C#語言的構造與特色,同時會採起簡潔的和你能理解的方式使用些代碼示例,咱們會盡可能讓你能稍微看看這些代碼就能理解這些概念。
注意:本文不是爲C#高手(C# gurus)所寫. 這是針對在C#學習上仍是初學者的文章。
下面是將要討論的C#問題的目錄:
程序結構 命名空間 數據類型 變量
運算符和表達式 枚舉
語句(Statements )
類(Classes)和結構(Structs) 修飾符(Modifiers) 屬性(Properties) 接口(Interfaces)
方法參數(Function Parameters) 數組(Arrays) 索引器(Indexers) 裝箱及拆箱操做 委託(Delegates) 繼承和多態
下面的內容將不會在被討論之列:
C++與C#誰更通用
諸如垃圾回收、線程以及文件處理等概念 數據的類型轉換 異常處理 .NET庫
------------------- 程序結構 編程
------------------ 數組
這一點象C++,C#是一種對大小寫字母敏感的語言,分號「;」是語句間的分隔符。與C++不一樣的是,C#當中聲明代碼文件(頭文件)與實現代碼文件(cpp文件)不是獨立存在的,全部代碼(類聲明和類實現)都位於一個擴展名爲cs的文件內。安全
讓咱們瞧瞧C#當中的Hello world程序是怎樣的。函數
using System; 學習
namespace MyNameSpace ui
{ this
class HelloWorld spa
{ 線程
static void Main(string[] args) 指針
{
Console.WriteLine ("Hello World");
}
}
}
在C#當中的每樣東西都被封裝到一個類中,C#的類又被封裝到一個命名空間當中(就象一個文件夾中的文件)。相似於C++,main方法是你的程序的入口點。C++的main函數調用名稱是"main",而C#的main函數是以大寫字母M起點的名稱是"Main"。
沒有必要把分號分隔符放在類語句塊或者結構定義語句塊後。這在C++當中被要求,但在C#當中卻不是。
-------------------
命名空間
-----------------
每個類都被包裝進一個命名空間。命名空間的概念與C++的徹底相同,但在C#當中使用命名空間的頻率較C++還高。你可使用點限定符(dot qulifier)訪問一個類。在上面的hello world程序當中MyNameSpace就是一個命名空間。
如今思考這樣的一個問題,你想從某些別的類的命名空間當中來訪問HelloWorld這個類如何操做。
這有一個例子:
using System;
namespace AnotherNameSpace
{
class AnotherClass
{
public void Func()
{
Console.WriteLine ("Hello World");
}
}
}
如今,從你的HelloWorld類裏你能象這樣去訪問上面的這個AnotherNameSpace的命名空間:
using System;
using AnotherNameSpace; // you will add this using statement
namespace MyNameSpace
{
class HelloWorld
{
static void Main(string[] args)
{
AnotherClass obj = new AnotherClass();
obj.Func();
}
}
}
在.NET庫當中,System是位於頂層的命名空間,別的命名空間都存在這個命名空間之下。默認狀態下,存在一個全局的命名空間,所以一個在命名空間外定義的類將直接在這個全局命名空間之下;所以,你能在沒有任何點限定符的狀況下訪問這個類。
你也能夠象下面這樣定義嵌套的命名空間。
Using C++當中的"#include"指示被C#的"using"關鍵字取代,它後面跟着一個命名空間的名字。正如上面的"using System"。"System"是別的全部被封裝的命名空間和類中最底層的命名空間。全部對象的基類都是System命名空間內的Object類派生的。
------------------
變量
-------------------
除如下區別外,C#當中的變量幾乎與C++同:
與C++不一樣,C#變量被訪問以前必須被初始化;不然編譯時會報錯。所以,訪問一個未初始化變量是不可能的事。
C#中你不會訪問到一個不肯定的指針。(譯者注:嚴格提及來C#已經把指針概念異化,限制更嚴格。因此有些資料上會說C#取消了指針概念) 一個超出數組邊界的表達式是不可訪問的。 C#中沒有全局的的變量或全局函數,全局方式的操做是經過靜態函數和靜態變量來實現的。
------------------- 數據類型
-------------------
全部C#數據類型都派生自基類Object。這裏有兩類數據類型:
基本型/內置型 用戶自定義型
下面一個C#內置類型列表:
類型 字節數 解釋
byte 1 無符號字節型 sbyte 1 有符號字節型 short 2 有符號短字節型 ushort 2 無符號短字節型 int 4 有符號整型 uint 4 無符號整型 long 8 有符號長整型 ulong 8 無符號長整型 float 4 浮點數 double 8 雙精度數 decimal 8 固定精度數 string Unicode 字串型 char Unicode 字符型 bool 真假 布爾型
注意:C#當中的類型範圍與C++有所不一樣;例如,C++的long型是4個字節,而在C#當中是8個字節。一樣地,bool型和string型都不一樣於C++。bool型只接受true和false兩種值。不接受任何整數類型。
用戶定義類型包括:
類類型(class) 結構類型(struct) 接口類型(interface)
根據數據類型的內存分配形式的不一樣又把它們分紅了兩種類型:
值類型(value Types)
引用類型(Reference Types)
值類型:
值類型數據在棧中分配。他們包括:全部基本或內置類型(不包括string類型)、結構類型、枚舉類型(enum type)
引用類型:
引用類型在堆中分配,當它們再也不被使用時將被垃圾收集。它們使用new運算符來建立,對這些類型而言,不存在C++當中的delete操做符,根本不一樣於C++會顯式使用delete這個運算符去釋放建立的這個類型。C#中,經過垃圾收集器,這些類型會自動被收集處理。
引用類型包括:類類型、接口類型、象數組這樣的集合類型類型、字串類型。
枚舉類型與C++當中的概念很是類似。它們都經過一個enum關鍵字來定義。
示例:
enum Weekdays {
Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday }
類類型與結構類型的比較
除了在內存分配形式上外,類與結構的概念徹底與C++相同。類的對象被分配在堆中,而且經過new來建立,結構也是被new建立但卻被分配在棧當中。C#當中,結構型適於快速訪問和擁有少許成員的數據類型。若是涉及量較多,你應該建立一個類來實現他。
(譯者注:這與堆和棧內存分配結構的特色有關。簡而言之,棧是一種順序分配的內存;堆是不必定是連續的內存空間。具體內容須要你們參閱相關資料)
示例:
struct Date {
int day; int month; int year; }
class Date {
int day; int month;
int year;
string weekday;
string monthName;
public int GetDay()
{
return day;
}
public int GetMonth()
{
return month;
}
public int GetYear()
{
return year;
}
public void SetDay(int Day)
{
day = Day
}
public void SetMonth(int Month)
{
month = Month;
}
public void SetYear(int Year)
{
year = Year;
}
public bool IsLeapYear()
{
return (year/4 == 0);
}
public void SetDate (int day, int month, int year)
{
}
...
}
-------------------
屬性
-------------------
若是你熟悉
C++
面象對象的方式,你就必定有一個屬性的概念。在上面示例當中,以
C++
的觀點來看,
Data
類的屬性就是
day
、
month
和
year
。用
C#
方式,你能夠把它們寫成
Get
和
Set
方法。
C#
提供了一個更方便、簡單、直接的方式來訪問屬性。
所以上面的類能夠被寫成:
using System;
class Date
{
public int Day{
get {
return day;
}
set {
day = value;
}
}
int day;
public int Month{
get {
return month;
}
set {
month = value;
}
}
int month;
public int Year{
get {
return year;
}
set {
year = value;
}
}
int year;
public bool IsLeapYear(int year)
{
return year%4== 0 ? true: false;
}
public void SetDate (int day, int month, int year)
{
this.day = day;
this.month = month;
this.year = year;
}
}
你可在這裏獲得並設置這些屬性:
class User
{
public static void Main()
{
Date date = new Date();
date.Day = 27;
date.Month = 6;
date.Year = 2003;
Console.WriteLine("Date: {0}/{1}/{2}", date.Day,
date.Month,
date.Year);
}
}
-------------------
修飾符
-------------------
你必須已經知道
public
、
private
、
protected
這些常在
C++
當中使用的修飾符。這裏我會討
論一些
C#
引入的新的修飾符。
readonly
(只讀)
readonly
修飾符僅在類的數據成員中使用。正如這名字所提示的,
readonly
數據成員僅能
只讀,
它們只能在構造函數或是直接初始化操做下賦值一次。
readonly
與
const
數據成員不
同,
const
要求你在聲明中初始化,這是直接進行的。看下面的示例代碼:
class MyClass
{
const int constInt = 100; //
直接初始化
readonly int myInt = 5; //
直接初始化
readonly int myInt2; //
譯者注:僅作聲明,未作初始化
public MyClass()
{
myInt2 = 8; //
間接的
}
public Func()
{
myInt = 7; //
非法操做(譯者注:不得賦值兩次)
Console.WriteLine(myInt2.ToString());
}
}
sealed
(密封)
密封類不容許任何類繼承,它沒有派生類。所以,你能夠對你不想被繼承的類使用
sealed
關鍵字。
sealed class CanNotbeTheParent
{
int a = 5;
}
unsafe
(不安全)
你可以使用
unsafe
修飾符來定義一個不安全的上下文。
在不安全的上下文裏,
你能寫些如
C++
指針這樣的不安全的代碼。看下面的示例代碼:
public unsafe MyFunction( int * pInt, double* pDouble)
{
int* pAnotherInt = new int;
*pAnotherInt = 10;
pInt = pAnotherInt;
...
*pDouble = 8.9;
}
-------------------
interface
(接口)
-------------------
若是你有
COM
方面的概念,
你會馬上明白我要談論的內容。
一個接口就是一個抽象的基類,
這個基類僅僅包含功能描述,而這些功能的實現則由子類來完成。
C#
中你要用
interface
關
鍵字來定義象接口這樣的類。
.NET
就是基於這樣的接口上的。
C#
中你不支持
C++
所容許的
類多繼承(譯者注:
即一個派生類能夠從兩個或兩個以上的父類中派生)。
可是多繼承方式
能夠經過接口得到。也就是說你的一個子類能夠從多個接口中派生實現。
using System;
interface myDrawing
{
int originx
{
get;
set;
}
int originy
{
get;
set;
}
void Draw(object shape);
}
class Shape: myDrawing
{
int OriX;
int OriY;
public int originx
{
get{
return OriX;
}
set{
OriX = value;
}
}
public int originy
{
get{
return OriY;
}
set{
OriY = value;
}
}
public void Draw(object shape)
{
... // do something
}
/ class's own method
public void MoveShape(int newX, int newY)
{
.....
}
}
-------------------
Arrays
(數組)
-------------------
C#
中的數組比
C++
的表現更好。數組被分配在堆中,所以是引用類型。你不可能訪問超出
一個數組邊界的元素。所以,
C#
會防止這樣類型的
bug
。一些輔助方式能夠循環依次訪問
數組元素的功能也被提供了,
foreach
就是這樣的一個語句。
與
C++
相比,
C#
在數組語法上
的特色以下:
方括號被置於數據類型以後而不是在變量名以後。
建立數組元素要使用
new
操做符。
C#
支持一維、多維以及交錯數組(數組中的數組)。
示例:
int[] array = new int[10]; //
整型一維數組
for (int i = 0; i < array.Length; i++)
array = i;
int[,] array2 = new int[5,10]; //
整型二維數組
array2[1,2] = 5;
int[,,] array3 = new int[5,10,5]; //
整型的三維數組
array3[0,2,4] = 9;
int[][] arrayOfarray = = new int[2]; //
整型交錯數組(數組中的數組)
arrayOfarray[0] = new int[4];
arrayOfarray[0] = new int[] {1,2,15};
索引器
-------------------
索引器被用於寫一個訪問集合元素的方法,集合使用
"[]"
這樣的直接方式,相似於數組。你
所要作的就是列出訪問實例或元素的索引清單。
類的屬性帶的是輸入參數,
而索引器帶的是
元素的索引表,除此而外,他們兩者的語法相同。
示例:
注意:
CollectionBase
是一個製做集合的庫類。
List
是一個
protected
型的
CollectionBase
成員,儲存着集合清單列表。
class Shapes: CollectionBase
{
public void add(Shape shp)
{
List.Add(shp);
}
//indexer
public Shape this[int index]
{
get {
return (Shape) List[index];
}
set {
List[index] = value
}
}
}
------------------
裝箱和拆箱操做(
Boxing/Unboxing
)
-------------------
C#
的裝箱思想是全新的。上面提到過全部的數據類型,不論內置或用戶自定義,全都從命
名空間
System
的一個基類
object
派生出來。所以把基本的或者原始類型轉換成
object
類
型被稱作裝箱,反之,這種方式的逆操做被稱爲拆箱。
示例:
class Test
{
static void Main()
{
int myInt = 12;
object obj = myInt //
裝箱
int myInt2 = (int) obj; //
拆箱
}
}
示例展現了裝箱和拆箱操做。一個整型值轉換成
object
類型,而後又轉換回整型。當一個
值類型的變量須要轉換成引用類型時,一個
object
的箱子會被分配容納這個值的空間,這
個值會被複制進這個箱子。拆箱與此相反,一個
object
箱子中的數據被轉換成它的原始值
類型時,這個值將被從箱中複製到適當的存儲位置。