類和結構實際上都是創建對象的模板,每個對象都包含數據,並提供羅勒處理和訪問數據的方法。類定義了每個類對象(實例)可以包含什麼數據和功能。例如一個類表示一個顧客,就可以定義字段CustomerID,FirstName,LastName和Address,以及 包含該顧客的信息,還可以定義處理存儲在這些字段中的數據的功能。
結構與類的區別是它們在內存中的存儲方式(類是存儲在堆(heap)上的引用類型,而結構是存儲在堆棧(stack)上的值類型)、訪問方式和一些特性(如結構不支持繼承)。較小的數據類型使用結構可提高性能。但在語法上,結構與類非常相似,主要區別是使用關鍵字struct代替class來聲明結構
對於類和結構,都使用關鍵字new來聲明實例:這個關鍵字創建對象並對其進行初始化。
類成員
類中的數據和函數稱為類的成員。除了這些成員外,類還可以包含嵌套的類型(例如其他類)。類中的所有成員都可以聲明為public或private。
數據成員
數據成員包含了類的數據——字段、常量和事件。數據成員可以是靜態數據(與整個類相關)或實例數據(類的每個實例都有它自己的數據副本)。通常,對於面向對象的語言,類成員總是實例成員,除非用static進行了顯式聲明。
字段是於類相關的變量。前面的例子已經使用了Customer類中的字段,一旦實例化Customer對象,就可以使用語法Object.FIEldName來訪問這些字段。
常量與類的關聯方式同變量與類的關聯方式一樣。
事件是類的成員,在發生某些行為(如改變類的字段或屬性,或者進行了某種形式的用戶交互操作)時,它可以讓對象通知調用程序。
函數成員
函數成員提供了操作類中數據的某些功能,包括方法、屬性、構造函數和終結器(finalizer)、運算符以及索引器。
方法是與某個類相關的函數,它們可以是實例方法,也可以是靜態方法。實例方法處理類的某個實例,靜態方法提供了更一般的功能,不需要實例化一個類。
屬性是可以在客戶機上訪問的函數組,其訪問方式與訪問類的公共字段類似。
構造函數是在實例化對象時自動調用的函數。它們必須與所屬類同名,且不能有返回類型。構造函數用於初始化字段的值。
終結器(析構函數)類似於構造函數,它們的名稱與類相同,但前面有一個~符號。終結器在C#中用得少,因為CLR會自動進行垃圾收集。另外不可能預測什麼時候調用終結器。
運算符執行的最簡單的操作就是+和-。C#還允許指定把已有的運算符應用於自己的類(運算符重載)。
索引器允許對象以數組或集合的方式進行索引。
方法
方法的聲明
在C#中,每個函數成員都必須與類或結構相關。正式的C#術語實際上區分了函數和方法:“函數成員”不僅包含方法,而且月包含類或結構的一些非數據成員,例如索引器、運算符、構造函數和析構函數等,甚至還有屬性。
在C#中,每個方法都單獨聲明為public或private,不能使用public:塊把幾個方法定義組合起來。所有的C#方法都在類定義中聲明和定義。方法的定義包括方法的修飾符、返回值的類型、方法名、輸入參數的列表和方法體。
[modifIErs] return_type MethodName([Parameters])
...{
Method body
}
每個參數都包括參數的類型名及在方法體中的引用名稱。但如果方法體有返回值,return語句就必須與返回值一起使用,以指定出口點。
public bool Test(int x,int y)
...{
return (x==y);
}
如果方法沒有返回值,就把返回類型指定為void。如果不帶參數,仍需要在方法名後面寫上一對空的圓括號()。此時return語句是可選的,注意方法可以包含任意多個return語句。
public bool Test(int value)
...{
if(value<0)
...{
return false;
}
return true;
}
調用方法
C#中調用方法時,必須使用圓括號。下面的例子MathTest說明了類的定義和實例化、方法的定義和調用的語法。
using System;
namespace Ling.Note.One
...{
class MainEnterpoint
...{
static void Main()
...{
Console.WriteLine("Pi is "+MathTest.GetPi());
MathTest math=new MathTest();
math.value = 30;
Console.WriteLine("Value fIEld of "+ math.value);
Console.WriteLine("Square is"+ math.Getsquare());
}
}
class MathTest
public int value;
public int Getsquare()
...{
return value*value;
}
public static double GetPi()
...{
return 3.14159;
}
}
}
給方法傳遞參數
參數可以通過引用或值傳遞給方法。在變量通過引用傳遞給方法時,被調用的方法得到的就是這個變量,所以在方法內部對變量進行的任何改變在方法退出後仍舊發揮作用。而如果變量是通過值傳遞給方法的,被調用的方法得到的是變量的一個副本,在方法退出後,對變量進行的修改會丟失。
C#中所有參數都是通過值來傳遞的,除非特別說明。
using System;
namespace Ling.Note.One
...{
class ParameterTest
...{
static void SomeFunction(int[] ints,int i)
...{
ints[0]=100;
i=100;
}
public static int Main()
...{
int i=0;
int[] ints=...{0,1,2,4,8};
SomeFunction(ints , i);
Console.WriteLine("i =" + i );
Console.WriteLine("ints[0] =" + ints[0] );
}
}
}
結果是i=0,ints[0]=100。注意字符串是不同的,因為字符串是不能改變的(如果改變字符串的值,就會創建一個全新的字符串),所以字符串無法采用一般引用類型的行為方式。在方法調用中,對字符串所做的任何改變都不會影響原來的字符串。
ref參數
通過值傳遞變量是默認的,也可以迫使值參數通過引用方式傳送給方法。需要使用ref關鍵字。如果把一個參數傳遞給方法,且這個方法的輸入參數前帶有ref關鍵字,則該方法對變量所作的任何改變都會影響原來對象的值。
static void SomeFunction(int[] ints, ref int i)
...{
ints [0] =100;
i=100;
}
在調用該方法時,還需要添加ref關鍵字:
SomeFunction(ints, ref i);
out關鍵字
C#要求變量在被引用前必須用一個初值進行初始化。盡管在把輸入變量傳遞給函數前,可以用沒有意義的值初始化它們,因為函數將使用真實、有意義的值初始化它們,但這樣做是沒有必要的,有時甚至會引起混亂。C#編譯器使用out關鍵字來初始化輸入參數,當在方法的輸入參數前面加上out關鍵字時,傳遞給該方法的變量可以不初始化。該變量通過引用傳遞,在調用該方法時,還需要使用out關鍵字,與在定義該方法時一樣
static void SomeFunction(out int i)
...{
i=100;
}
public static int Main()
...{
int i;
SomeFunction(out i);
Console.WriteLine(i);
return 0;
}
&nout關鍵字是C#中的新增內容,該關鍵字的引入使C#更安全,更不容易出錯。
方法的重載
C#支持方法的重載——方法的幾個不同簽名(名稱,參數個數,參數類型)的版本,為了重載方法,只需要聲明同名但參數個數或類型不同的方法即可。
class Test
...{
void DOSomething(string result)
...{
.........
}
void DOSomething(int result)
...{
..........
}
}
因為C#不支持可選參數,所以需要使用方法重載來達到此目的。
class MyClass
...{
int DOSomething(int x)
DOSomething(x,10);
}
int DOSomething(int x,int y)
...{
.........
}
}
兩個方法不能僅在返回類型上有區別,不能僅根據參數是聲明為ref還是out來區分。
屬性
屬性是一個方法或一對方法,在客戶機代碼看來,他們是一個字段。
mainForm.Height = 400;
在語法上,上面的代碼類似於設置一個字段,但實際上是調用了屬性訪問器,它包含的代碼重新設置了窗體的大小。
在C#中定義屬性,可以使用下面的語法:
public string SomeProperty
...{
get
...{
return "this is the property value";
}
set
.............
}
}
get訪問器不帶參數,且必須返回屬性聲明的類型。也不應為set訪問器指定任何顯式參數,但編譯器假定它帶一個參數,其類型也於屬性相同,並表示為value。
private string foreName;
public string ForeName
...{
get
...{
return foreName;
}
set
...{
if(value.Length > 20)
...{
......
}
else
foreName = value;
}
}
}
在屬性定義中省略set訪問器,就可以創建只讀屬性。
private string foreName;
public string ForeName
...{
get
...{
return foreName;
}
}
同樣,在屬性定義中省略get訪問器,就可以創建只寫屬性。
C#允許給屬性的get和set訪問器設置不同的訪問修飾符,在get和set訪問器中,必須有一個具備屬性的訪問級別。
待續。。。