C#教程第五課:方法
2024-07-21 02:22:23
供稿:網友
 
本節課向你介紹c#的方法,其目的是:
1.了解方法的結構格式
2.了解靜態和實例方法之間的區別
3.學會實例對象的使用
4.學會如何調用實例化的對象
5.學會方法的四種參數類型的使用
6.學會使用"this"引用
以往,對于每個程序來說,所有的工作都在main()方法中實現。這對于功能簡單的程序是合適的,因為僅僅用來學習一些概念。有個更好的方法來組織你的程序,那就是使用方法。方法是很有用的,因為方法可以讓你在不同的單元中分開設計你的邏輯模塊。
方法的結構格式如下:
屬性 修飾符 返回值類型 方法名(參數) { 語句 } 
我們將在后面的課程中,討論屬性和修飾符。方法的返回值可以是任何一種c#的數據類型,該返回值可以賦給變量,以便在程序的后面部分使用。方法名是唯一,可以被程序調用。為使得你的代碼變得更容易理解和記憶,方法的取名可以同所要進行的操作聯系起來。你可以傳遞數據給方法,也可以從方法中返回數據。它們由大括號包圍起來。大括號中的語句實現了方法的功能。
1.清單5-1. 一個簡單的方法: onemethod.cs 
using system;
class onemethod {
public static void main() {
string mychoice;
onemethod om = new onemethod();
do {
mychoice = om.getchoice();
// make a decision based on the user's choice
switch(mychoice) {
case "a":
case "a":
console.writeline("you wish to add an address.");
break;
case "d":
case "d":
console.writeline("you wish to delete an address.");
break;
case "m":
case "m":
console.writeline("you wish to modify an address.");
break;
case "v":
case "v":
console.writeline("you wish to view the address list.");
break;
case "q":
case "q":
console.writeline("bye.");
break;
default:
console.writeline("{0} is not a valid choice", mychoice);
}
// pause to allow the user to see the results
console.write("press any key to continue...");
console.readline();
console.writeline();
} while (mychoice != "q" && mychoice != "q"); // keep going until the user wants to quit
}
string getchoice() {
string mychoice;
// print a menu
console.writeline("my address book/n");
console.writeline("a - add new address");
console.writeline("d - delete address");
console.writeline("m - modify address");
console.writeline("v - view addresses");
console.writeline("q - quit/n");
console.writeline("choice (a,d,m,v,or q): ");
// retrieve the user's choice
mychoice = console.readline();
return mychoice;
}
} 
說明 
1.清單5-1中的程序類似于第四課中的doloop程序。
區別在于:前一課中的程序打印出菜單內容,并在main()方法中接受用戶的輸入,而本課中,該功能用一個名為getchoice()的方法實現,該方法的返回值類型是個字符串類型。在main方法中,在switch語句中用到了該串。方法"getchoice"實現了調用時所完成的工作。方法名后面的括號內是空的,因為調用getchoice()方法時,不需要傳遞任何數據。
2.在方法塊中,我們首先定義了變量"mychoice"。
雖然它與 main()方法中的"mychoice"變量同名同類型, 但它們是不同的兩個變量,因為局部變量僅僅在其定義的塊內可見。換句話說, getchoice()方法中的"mychoice" 同main()方法中的"mychoice"變量沒有絲毫聯系。getchoice()方法打印出一個菜單到控制臺,并讀取用戶的輸入。"return" 語句把"mychoice"變量值返回給main()方法中的調用者getchoice()。注意: "return"語句返回類型同該方法中定義的返回值類型相同,本例中,該返回值是個字符串。
3.在main()方法中,在使用getchoice()之前,實例化了一個新的"onemethod"對象。
這是因為:我們沒有指明一個"靜態"修飾符。(注意:main()函數帶有"靜態"修飾符),getchoice()就成為一個實例的方法。 實例方法和靜態方法的區別是:前者可以創建多個類的實例,每個實例有自己的單獨的getchoice()方法。而一旦方法是靜態的,就不存在方法的實例,你只能調用該靜態方法的一個實現。
所以,正如前面所講的,因為getchoice()并不是靜態的,所以,我們必須實例化一個新對象來使用它。這是通過定義"onemethod om = new onemethod()"來進行的。在等號的左邊,是對象引用"om",其類型是onemethod。"om"是個對象的引用,這點很重要,"om"并不是對象自身,它是個引用onemethod類型對象的變量。 在等號的右邊,把新創建的onemethod對象賦給引用"om"。 關鍵字"new"是個在堆上創建對象的新實例的c#運算符。此處完成的工作是: 在堆上創建一個新的onemethod實例,并把它賦給om引用。一旦有了om引用的onemethod對象實例,就可以通過om引用來對實例進行處理。
方法,域和其他類成員可以通過"." (點)運算符進行訪問,標識和操縱。一旦需要調用方法getchoice(),就通過om引用,并使用點運算符"om.getchoice()"來進行。 getchoice() 塊中的語句執行完畢之后即返回。為了捕捉到getchoice()的返回值,我們使用了賦值運算符"="。 返回串放到了main()函數的局部變量 mychoice中,從那里,程序的其余部分按照前面課程中介紹的方式正常執行。
2.清單5-2. 方法參數:methodparams.cs 
using system;
class address {
public string name;
public string address;
}
class methodparams {
public static void main() {
string mychoice;
methodparams mp = new methodparams();
do {
// show menu and get input from user
mychoice = mp.getchoice();
// make a decision based on the user's choice
mp.makedecision(mychoice);
// pause to allow the user to see the results
console.write("press any key to continue...");
console.readline();
console.writeline();
} while (mychoice != "q" && mychoice != "q"); // keep going until the user wants to quit
}
// show menu and get user's choice
string getchoice() {
string mychoice;
// print a menu
console.writeline("my address book/n");
console.writeline("a - add new address");
console.writeline("d - delete address");
console.writeline("m - modify address");
console.writeline("v - view addresses");
console.writeline("q - quit/n");
console.writeline("choice (a,d,m,v,or q): ");
// retrieve the user's choice
mychoice = console.readline();
return mychoice;
}
// make decision
void makedecision(string mychoice) {
address addr = new address();
switch(mychoice) {
case "a":
case "a":
addr.name = "joe";
addr.address = "c# station";
this.addaddress(ref addr);
break;
case "d":
case "d":
addr.name = "robert";
this.deleteaddress(addr.name);
break;
case "m":
case "m":
addr.name = "matt";
this.modifyaddress(out addr);
console.writeline("name is now {0}.", addr.name);
break;
case "v":
case "v":
this.viewaddresses("cheryl", "joe", "matt", "robert");
break;
case "q":
case "q":
console.writeline("bye.");
break;
default:
console.writeline("{0} is not a valid choice", mychoice);
}
}
// insert an address
void addaddress(ref address addr) {
console.writeline("name: {0}, address: {1} added.", addr.name, addr.address);
}
// remove an address
void deleteaddress(string name) {
console.writeline("you wish to delete {0}'s address.", name);
}
// change an address
void modifyaddress(out address addr) {
//console.writeline("name: {0}.", addr.name); // causes error!
addr = new address();
addr.name = "joe";
addr.address = "c# station";
}
// show addresses
void viewaddresses(params string[] names) {
foreach (string name in names) {
console.writeline("name: {0}", name);
}
}
} 
說明 
1.清單5-2是清單5-1的修改,主要是對程序進行了模塊化,并添加了更多的實現,以便闡述參數傳遞的用法。
c#可以處理四種類型的參數:out(輸出),ref(引用),params(數組)和value(值)。為了說明參數的用法,我們用兩個字符串域創建地址類。
2.在main()方法中,我們調用getchoice()來讀取用戶的輸入,并且把字符串放到mychoice變量中。
之后,把mychoice變量作為makedecision()函數的實在參數。在實現makedecision()方法時,注意其形式參數為字符串mychoice。需要再次說明的是:這是個新的mychoice變量,不同于調用者的實在參數,僅僅是適用于本方法的局部變量。 因為makedecision()方法的mychoice參數沒有任何其他修飾符,故認為它是"值"參,即實在參數的值被拷貝到棧中,故作為值參的變量是局部的,任何對局部變量值的改變并不影響到調用者的實在參數的值。換句話說,值參僅僅是來自調用者的輸入。
3.makedecision()方法中的switch語句完成如下功能:
在每種情形下,都調用相應的方法。這些方法的調用不同于main()方法。除了使用"mp" 引用,它們還使用了"this"關鍵字。"this"是對當前對象的引用。由于makedecision()方法不是靜態方法,當前對象已經被實例化,所以可以使用"this"引用來調用同一實例中的方法。
4.addaddress()方法用到了"ref"參數,即引用可作為參數來傳遞,即該引用被拷貝到棧中,其引用的對象同調用者的實參所引用的對象是同一個。
這意味著:任何對局部引用的對象的改變也就是對調用者所引用的對象的改變。你可以想象一下,這就相當于輸入/輸出參數。
5.modifyaddress()中有一個輸出參數。
輸出參數僅僅傳遞給被調用函數。一旦調用該方法時,在棧中的僅有的一個引用未被賦值,因為根據賦值的確定性原則,在該變量沒有被賦值之前,就不能使用該變量。modifyaddress()方法的第一行作為注釋,說明了這一點。你可以試著去掉注釋符,編譯一下程序,看看結果如何。一旦該變量被賦了值,在程序返回之后,輸出參數就被拷貝到調用者的參數中。所以,在方法返回之前,必須給輸出參數賦值。
小結
c# 語言的一個很有用途的參數類型是數組參數,它須是一維或多維的數組。在makedecision()方法中,我們傳遞了用四個逗號隔開的字符串參數。參數的個數是變量。在viewaddresses()方法中,使用了foreach循環,逐一輸出這些字符串。數組參數僅是一種輸入性質的參數,任何對數組參數值的改變僅僅影響到局部的副本值。
概括地講,你現在已經理解了方法的組織結構。你還了解了方法的實現可以采用的四種參數類型及其格式。 一旦你使用實例方法,就必須實例化該對象,靜態方法則不同,后者可以在任何時候被調用。另外,你也了解了"this"引用是如何調用實例方法的。