天天看點

C#學習之類

類的成員包括資料成員和函數成員,成員的可通路性可以是public、protected、internal protected、private和internal

資料成員

資料成員包含類的資料------字段、常量和事件的成員。字段是與類相關的變量;常量與類的關聯方式同變量與類的關聯方式,使用const關鍵字來聲明常量,如果寫為public就可以在類的外部進行通路;事件是類的成員,在發生某些行為時,它可以讓對象通知調用方。

函數成員

函數成員提供了操作類中資料的某些功能,包括方法、屬性、構造函數和終結器、運算符以及索引器。

1.方法

方法是與某個類相關的函數,與資料成員一樣,函數成員預設為執行個體成員,使用static修飾符可以把方法定義為靜态方法。 (1)方法的聲明 在C#中,方法的定義包括任意方法修飾符、傳回值的類型,然後依次是方法名和輸入參數清單(用圓括号括起來)和方法體。 【modifier】 return_type MethodName(Parameters) { //Method Body //Do something } 每個參數都包括參數的類型名和在方法體中的引用名稱,但如果方法體有傳回值,return語句就必須與傳回值一起使用,以制定出口點。例如:

public ind add(int a,int b)
{
      return a+b
}
           

( 2 )調用方法 由于方法是在類中的,是以在每次調用類中的方法時,需要對類執行個體化,除非是一個靜态類,然後通過執行個體化後的對象通過“.”運算符執行所要調用的方法,調用方法時需要注意這個方法的參數和傳回值類型。 (3)給方法傳遞參數 參數可以通過引用或通過值傳遞給方法。在變量通過引用傳遞給方法時,被調用的方法得到的就是這個變量,是以在方法内部對變量進行的任何改變在方法退出後仍舊有效。而如果變量通過值傳遞給方法,被調用的方法得到的是這個變量的一個副本,也就是在方法中重新生成一個具有相同類型的變量,這個變量存儲着傳進來的值,方法對該變量的修改是對方法内生成的變量進行修改,當方法執行完成以後,方法内生成的變量将被釋放,則對其的修改結果也會消失。對于複雜的資料類型,按引用傳遞的效率會更高,因為在按值傳遞時,必須複制大量的資料。例如:

using System;
namespace Wrox
{
    class ParameterTest
   {
         static void SomeFunction(int[] ints,int i)
	{
		ints[0] = 100;
		i = 100
	} 
	public static int Main()
	{
   		int i =0;
	 	int[] ints={1,2,3,4};
  		Console.WriteLine("i="+i);
  		Console.WriteLine("ints[0]=" + ints[0]);
   		Console.WriteLine("Calling SomeFunction");
		SomeFunction(ints,i);
  		Console.WriteLine("i="+i);
  		Console.WriteLine("ints[0]=" + ints[0]);
		return 0;
	}
    }
}
           

結果是: i = 0; ints[0] = 1 Calling SomeFunction i=0; ints[0]=100 (4)ref參數 通過值傳送變量是預設的,也可以迫使值參數通過引用傳遞給方法,為此,要使用ref關鍵,如果把一個參數傳遞給方法,且這個方法的輸入參數帶有ref關鍵字,則該方法對變量所做的任何改變都會影響到原始對象的值。

static void SomeFunction(int[] ints,ref int i)
{
       ints[0] = 100;
       i = 100;
}
           

在調用該方法的時候,還需要添加ref關鍵字,即   SomeFunction(ints,ref i); (5)out 參數 C#要求變量在被引用前必須用一個初值進行初始化,盡管在把輸入變量傳遞給函數前,可以用沒有意義的值初始化它們,因為函數将使用真實,有意義的值初始化它們,但是這樣做是沒有必要的,有時甚至會引起混亂。但又一種方法能夠簡化C#編譯器所堅持的輸入參數初始化。編譯器使用out關鍵字來初始化,在方法的輸入參數前面加上out字首時,傳遞給該方法的變量可以不初始化。在調用該方法時,還需要使用out關鍵字,與定義該方法時一樣。

static void SomeFunction(out int i)
{
	i = 100;
}
public static int Main()
{
	int i ;
	SomeFunction(i);
	Console.WriteLine(i);
	return 0;
}
           

(6)命名參數 參數一般需要按定義的順序傳送給方法。命名參數允許按任意順序傳遞。例如:

string FullName(string firstName,string lastName)
{
	return firstName+" "+lastName;
}
FullName("John","Doe");
FullName(lastName:"Doe",firstName:"John");
           

如果方法有幾個參數,就可以在同一個調用中混合使用位置參數和命名參數。 (7)可選參數 參數也可以是可選的,必須為可選參數提供預設值,可選參數還必須是方法定義的最後一個參數。例如:

void TestMethod (int notOptionalNumber,int optionalNumber = 10)
{
	System.Console.Write(optionalNumber+notOptionalNumber);
}
           

(8)方法的重載 C#支援方法的重載,這一點與Java和C++類似,即方法名相同,但參數的個數或類型不同。 C#在重載方法的參數方面有一些小限制:

  • 兩個方法不能僅在傳回類型上有差別
  • 兩個方法不能僅根據參數是聲明ref還是out來區分

2.屬性

屬性的概念是:它是一個方法或一對方法,在用戶端代碼看來,它們是一個字段。 在C#中定義屬性,可以使用如下的文法:

public string SomeProperty
{
	get
	{
		return "This is the Property value";
	}
	set
	{
		//do whatever needs to be done to set the property
	}
}
           

get通路器不帶任何參數,且必須傳回屬性聲明的類型。也不應為set通路器制定任何顯式參數,但編譯器假定它帶一個參數,其類型也與屬性相同,并表示為value。例如:

private int age
publicc int Age
{
	get
	{
		return age;
	}
	set
	{
		age = value;
	}
}
           

(1)隻讀和隻寫屬性 在屬性定義中省略set通路器,就可以建立隻讀屬性。同樣,在屬性定義中省略get通路器,就可以建立隻寫屬性。但是,這是不好的程式設計方式,因為這可能會使用戶端代碼的作者感到迷惑。 (2)屬性的通路修飾符 C#允許給屬性的get和set通路器設定不同的通路修飾符,是以屬性可以有公有的get通路器和私有受保護的set通路器。這有助于控制屬性的設定方式和時間。 (3)自動實作屬性 如果屬性的set和get通路器中沒有任何邏輯,就可以使用自動實作屬性。這種屬性會自動實作後備成員變量,前面的age示例代碼如下: public int Age{get;set;} 不需要聲明private int age。編譯器會自動建立它。使用自動實作屬性,就不能再屬性設定中驗證屬性的有效性。

3.構造函數

聲明基本構造函數的文法就是聲明一個與包含的類同名的方法,但是該方法沒有傳回類型:

public class MyClass
{
     public MyClass()
    {

    }
}
           

一般情況下,如果沒有提供任何構造函數,編譯器會在背景建立一個預設的構造函數,這是一個非常基本的構造函數,它隻能把所有的成員字段初始化為标準的預設值。構造函數的重載遵循與其他方法相同的規則,換言之,可以為構造函數提供任意多的重載,隻要他們的簽名有明顯的差別即可:

public MyClass()
{
        //construction code
}
public MyClass(int number)
{
       //construction code
}	
           

但注意,如果提供了帶參數的構造函數,編譯器就不會自動提供預設的構造函數。隻有在沒有定義任何構造函數時,編譯器才會自動提供預設的構造函數。

public class MyNumber{
      private int number;
      public int MyNumber(int number)
     {
          this.number = number;
     }
}
           

這一段代碼還說明,一般使用this關鍵字區分成員字段和同名的參數,如果試圖使用無參數的構造函數執行個體化MyNumber對象,就會的到編譯錯誤。 (1)靜态構造函數 C#的一個新特征就是可以給類編寫無參數的靜态構造函數,這種函數隻執行一次,而前面的構造函數都是執行個體構造函數,隻有在建立類的對象時,才會執行它。

class MyClass()
{
    static MyClass()
    {
            //initialization code
     }
}
           

編寫靜态構造函數的一個原因是,類有一些靜态字段或屬性,需要在第一次使用類之前,從外部源中初始化這些靜态字段和屬性。 需要注意的是:靜态構造函數是沒有通路修飾符,其它C#代碼從來不調用它,但在加載類時,總是由.net運作庫調用它,是以像public或private這樣的通路修飾符沒有任何意義。出于同樣的原因,是以靜态構造函數也不帶有任何的參數,一個類也隻能有一個靜态構造函數。 (2)從構造函數中調用其它的構造函數 有時,在一個類中有幾個構造函數,以容納某些可選的參數,這些構造函數包含有一些共同的代碼。例如:

class car
{
    private string description;
    private uint nWheels;
    public car(string description,uint nWheels)
    {
           this.description = description;
           this.nWheels = nWheels;
     }

     public car()
    {
         car("Very Good",5);
     }
}
           

C#構造函數初始化器可以包含對同一個類的另一個構造函數的調用,也可以包含對直接基類的構造函數的調用。