呼叫 .NET Class Library 中不同類型的方法

已完成

我們先前在使用 Console.WriteLine() 方法時,從第一行程式碼便開始在呼叫方法。 並非所有類別與方法都是以相同方式實作。 此單元將會涵蓋一些最熱門的變體,這些變體是您在使用來自 .NET Class Library 的方法時所應該了解的。 更重要的是,您將會了解如何尋找並使用文件以進一步了解每個方法。

如何呼叫 .NET Class Library 中的方法

根據您先前使用 Console.WriteLine() 方法的經驗,您應該已經知道基本概念:

  • 一開始,請輸入類別名稱 Console
  • 新增成員存取運算子,也就是 . 符號
  • 新增方法的名稱 WriteLine
  • 新增方法叫用運算子,也就是一組括弧 ()
  • 最後,將想要以 Console.WriteLine() 方法列印為輸入參數的值新增至左括弧與右括弧之間 (例如,"Hello World!")

(選擇性) 根據開發人員設計及實作指定方法的方式,您可能也需要:

  • 將其他值傳遞為輸入參數
  • 接受傳回值

我們將會在下一個單元中涵蓋輸入參數與傳回值。

雖然某些方法可以利用與 Console.WriteLine() 相同的方式呼叫,.NET Class Library 中還有其他方法需要使用不同的方式。

呼叫 .NET Class Library 中不同類型的方法

下列範例會透過產生亂數並將它列印至主控台,來模擬投擲骰子的情況。

Random dice = new Random();
int roll = dice.Next(1, 7);
Console.WriteLine(roll);

如果您多次執行該程式碼,系統將會在主控台輸出中顯示介於 1 到 6 之間的數字。

首先,讓我們逐步解說每個程式碼所完成的作業,然後我們將會針對使用 .NET Class Library 中的類別與方法詢問一些重要的問題並做出一些觀察。

第一行程式碼會建立 .NET Class Library 中 System.Random 類別的新執行個體,並將參考儲存至名為 dice 之變數的新物件中。

第二行程式碼會呼叫 dice 物件的 Next() 方法,並傳遞兩個參數:亂數的最小值與最大值。 Next() 方法會傳回值,我們會將它儲存至名為 roll 的變數中。

第三行程式碼會呼叫 WriteLine() 方法,以將 roll 的值列印至主控台。

在此程式碼範例中,我們會呼叫 Random 類別和 Console 類別的方法。 不過,我們呼叫這些方法的「方式」並不相同。 我們之所以會使用不同的方式來呼叫它們,是因為某些方法是具狀態,而其他方法則是無狀態的。

具狀態與無狀態方法

在計算中,狀態 會描述執行環境在特定時間點的情況。 隨著您的程式碼逐步執行各行,值會被儲存在變數中。 在執行期間的任何時間點,應用程式的目前狀態便是儲存在記憶體中之所有值的集合。

某些方法不需仰賴應用程式的目前狀態便能正常運作。 換句話說,無狀態方法 的實作原因,便是因為它們可以在無需參考或變更儲存在記憶體中之任何值的情況下運作。 無狀態方法也稱為 靜態方法

例如,Console.WriteLine() 方法不需要仰賴儲存在記憶體中的任何值。 它能在不以任何方式影響到應用程式狀態的情況下執行其功能並結束。

不過,其他方法則必須存取應用程式的狀態才能正常運作。 換句話說,具狀態方法 的建置方式,使它們必須仰賴由已執行的上一行程式碼儲存在記憶體中的值。 或者它們會透過更新記憶體中的值,或是將新值儲存在記憶體中來修改應用程式的狀態。 它們也稱為 執行個體方法

具狀態 (執行個體) 方法會在「欄位」中追蹤其狀態,這些欄位是在類別上定義的變數。 類別的每個新執行個體都會自行擁有那些欄位的複本,以在其中儲存狀態。

單一類別可以同時支援具狀態與無狀態方法。 不過,當您需要呼叫具狀態方法時,您必須先建立類別的「執行個體」,來使該方法可以存取狀態。

建立類別的執行個體

類別的執行個體稱為「物件」。 若要建立類別的新執行個體,您會使用 new 運算子。 請考慮下列程式碼,它會建立 Random 類別的新執行個體,以建立稱為 dice 的新物件:

Random dice = new Random();

new 運算子會執行數個重要工作:

  • 它會先要求電腦記憶體中的位址,該位址必須大到可以儲存以 Random 類別為基礎的新物件。
  • 它會建立新物件,並將它儲存在該記憶體位址。
  • 它會傳回記憶體位址,以將它儲存在 dice 變數中。

從那裡開始,在參考 dice 變數時,.NET 執行階段便會在幕後執行查詢,以營造出您是直接使用物件本身的假象。

為什麼 Next() 方法是具狀態的?

您可能會想知道為什麼 Next() 方法是實作為具狀態方法? 難道 .NET Class Library 設計人員找不出辦法在不需要狀態的情況下產生亂數? 而 Next() 方法所儲存或參考的確切內容又是什麼?

這些都是很合理的問題。 概括而言,電腦很擅長遵循特定指示來建立可靠且可重複的結果。 為了建立隨機性的假象,Next() 方法的開發人員決定擷取細微至將毫秒再加以細分的日期和時間,並使用它來植入每次都能產生不同數字的演算法。 雖然它並非完全隨機,但已足以供大部分的應用程式使用。 在 dice 物件存留期間擷取並維護的狀態,便是種子值。 針對 Next() 方法的每個後續呼叫都會重新執行該演算法,但會確保種子會變更,來使系統不 (一定) 會傳回相同的值。

不過,了解 Random.Next()「如何」運作,對於使用它來說並非必要。 重要的是要記得某些方法需要您在呼叫它之前先建立其類別的執行個體,而其他方法則不需要。

在呼叫某個類別的方法之前,要如何判斷是否需要先建立該類別的執行個體?

其中一個了解如何呼叫方法的方式是參考文件。 您將能找到說明該方法必須從物件執行個體呼叫,還是直接從類別呼叫的範例。

注意

文件的其中一個最實用部分就是程式碼範例,其示範如何使用您正在研究的方法。 有時候您需要在網頁上向下捲動,以尋找程式碼範例。

或者,您可嘗試直接從類別本身存取該方法。 就算不行,最糟糕的情況也只是收到編譯錯誤而已。

如果您將下列程式碼輸入 .NET 編輯器:

int result = Random.Next();

您將會看到紅色曲線,指出發生編譯錯誤。 將滑鼠游標暫留在紅色曲線上方時,您將能看到快顯視窗出現並顯示下列訊息:

(1,14): error CS0120: An object reference is required for the non-static field, method, or property 'Random.Next()'

概括回顧

  • 若要呼叫 .NET Class Library 中類別的方法,您會使用 ClassName.MethodName() 格式,其中 . 符號是用來存取定義於類別上之方法的成員存取運算子,而 () 符號則是方法叫用運算子。
  • 呼叫無狀態方法時,您不需要先建立其類別的新執行個體。
  • 呼叫具狀態方法時,您需要建立類別的執行個體,並存取物件上的方法。
  • 使用 new 運算子來建立類別的新執行個體。
  • 類別的執行個體稱為「物件」。