共用方式為


方法(C# 程式設計手冊)

方法是包含一系列陳述式的程式碼區塊。 程式透過呼叫方法並指定所需的參數來執行陳述式。 在 C# 中,每個執行的指示是在方法的內容中執行。

方法 Main 是每個 C# 應用程式的進入點,而且當程序啟動時,Common Language Runtime (CLR) 會呼叫它。 在使用 最上層語句的應用程式中,方法 Main 是由編譯程序產生,並包含所有最上層語句。

備註

本文討論具名方法。 如需匿名函式的資訊,請參閱 Lambda 運算式

方法簽名

方法會在類別結構介面中宣告,需指定存取層級,例如 publicprivate,也可以選擇性地使用修飾詞,例如 abstractsealed,以及設定傳回值、方法名稱和任何方法的參數。 這些部分共同構成方法的特徵。

這很重要

在方法多載的情境下,方法的返回類型不屬於方法簽名的一部分。 不過,在判斷委派與所指向的方法之間的相容性時,它是方法簽章的一部分。

方法參數會以括弧括住,並以逗號分隔。 空括弧表示方法不需要任何參數。 這個類別包含四種方法:

abstract class Motorcycle
{
    // Anyone can call this.
    public void StartEngine() {/* Method statements here */ }

    // Only derived classes can call this.
    protected void AddGas(int gallons) { /* Method statements here */ }

    // Derived classes can override the base class implementation.
    public virtual int Drive(int miles, int speed) { /* Method statements here */ return 1; }

    // Derived classes must implement this.
    public abstract double GetTopSpeed();
}

方法存取

在物件上呼叫方法就像存取欄位一樣。 在物件名稱之後,加入句點、方法的名稱和括弧。 自變數會列在括弧內,並以逗號分隔。 因此,可以呼叫 類別的方法 Motorcycle ,如下列範例所示:

class TestMotorcycle : Motorcycle
{
    public override double GetTopSpeed()
    {
        return 108.4;
    }

    static void Main()
    {
        TestMotorcycle moto = new TestMotorcycle();

        moto.StartEngine();
        moto.AddGas(15);
        moto.Drive(5, 20);
        double speed = moto.GetTopSpeed();
        Console.WriteLine($"My top speed is {speed}");
    }
}

方法參數與引數

方法定義會指定所需的任何參數的名稱和類型。 呼叫程式代碼呼叫 方法時,它會為每個參數提供稱為自變數的具體值。 自變數必須與參數類型相容,但呼叫端程式代碼中使用的自變數名稱(如果有的話)不必與 方法中定義的參數相同。 例如:

public void Caller()
{
    int numA = 4;
    // Call with an int variable.
    int productA = Square(numA);

    int numB = 32;
    // Call with another int variable.
    int productB = Square(numB);

    // Call with an integer literal.
    int productC = Square(12);

    // Call with an expression that evaluates to int.
    productC = Square(productA * 3);
}

int Square(int i)
{
    // Store input argument in a local variable.
    int input = i;
    return input * input;
}

參考傳遞與值傳遞

根據預設,當一個值類型的實例被傳遞至方法時,會傳遞其副本,而不是實例本身。 因此,對 自變數的變更不會影響呼叫方法中的原始實例。 若要以傳址方式傳遞實值型別實例,請使用 ref 關鍵詞。 如需詳細資訊,請參閱 傳遞 Value-Type 參數

當參考型別的對象傳遞至方法時,會傳遞對象的參考。 也就是說,方法不會接收物件本身,而是指出物件位置的自變數。 如果您使用這個參考來變更對象的成員,即使以傳值方式傳遞對象,變更也會反映在呼叫方法中的 自變數中。

您可以使用 關鍵字建立參考類型 class ,如下列範例所示:

public class SampleRefType
{
    public int value;
}

現在,如果您將以這個型別為基礎的對象傳遞至方法,則會傳遞對象的參考。 下列範例會將 型別 SampleRefType 的對象傳遞至 方法 ModifyObject

public static void TestRefType()
{
    SampleRefType rt = new SampleRefType();
    rt.value = 44;
    ModifyObject(rt);
    Console.WriteLine(rt.value);
}

static void ModifyObject(SampleRefType obj)
{
    obj.value = 33;
}

此範例基本上與上一個範例相同,因為它會依值將自變數傳遞至 方法。 但是,因為使用了參考型別,所以結果會有所不同。 在ModifyObject中對參數objvalue欄位所做的修改,亦在TestRefType方法中改變了引數rtvalue欄位。 TestRefType 方法將 33 顯示為輸出。

如需了解如何以傳址和傳值方式傳遞參考型別的詳細資訊,請參閱 傳遞 Reference-Type 參數參考型別

傳回值

方法可以傳回值給呼叫者。 如果傳回型別(方法名稱之前所列的類型)不是 void,則方法可以使用語句傳回值return。 具有 return 關鍵詞的 語句,後面接著符合傳回型別的值,會將該值傳回給方法呼叫端。

值可以透過傳值或 傳址 傳回給呼叫端。 如果在方法簽章中使用 ref 關鍵詞,而且該關鍵詞遵循在每一個 return 關鍵詞之後,則會以傳址方式將值傳回給呼叫端。 例如,下列方法簽章和 return 語句表示該方法會將名為estDistance的變數以參考傳遞給呼叫者。

public ref double GetEstimatedDistance()
{
    return ref estDistance;
}

return 關鍵字也會停止執行方法。 如果傳回類型為 void,不含值的 return 陳述式對於停止方法的執行仍很有用。 return如果沒有 關鍵詞,方法就會在到達程式代碼區塊的結尾時停止執行。 需要具有非 void 傳回型別的方法,才能使用 return 關鍵詞傳回值。 例如,這兩種方法使用 return 關鍵字傳回整數:

class SimpleMath
{
    public int AddTwoNumbers(int number1, int number2)
    {
        return number1 + number2;
    }

    public int SquareANumber(int number)
    {
        return number * number;
    }
}

若要使用從方法傳回的值,呼叫方法可以使用 方法呼叫本身,只要相同類型的值就已足夠。 您也可以將傳回值指派給變數。 例如,下列兩個程式代碼範例會達成相同的目標:

int result = obj.AddTwoNumbers(1, 2);
result = obj.SquareANumber(result);
// The result is 9.
Console.WriteLine(result);
result = obj.SquareANumber(obj.AddTwoNumbers(1, 2));
// The result is 9.
Console.WriteLine(result);

在此情況下, result使用局部變數來儲存值是選擇性的。 它可能有助於程式代碼的可讀性,或者如果您需要儲存方法整個範圍的自變數原始值,則可能是必要的。

若要使用方法所傳回的值,如果您想要修改其值,則必須宣告 ref 局部 變數。 例如,如果 Planet.GetEstimatedDistance 方法以傳址方式傳回 Double 值,您可以將它定義為具有類似下列程式代碼的 ref 局部變數:

ref double distance = ref Planet.GetEstimatedDistance();

從方法傳回多維度陣列, M如果呼叫函式將數位傳遞至 M,則不需要修改數位的內容。 您可以針對 M 值的良好樣式或功能流程,從 傳回產生的數位,但並非必要,因為 C# 會以傳值方式傳遞所有參考型別,而陣列參考的值是數位的指標。 在方法 M中,陣列內容的任何變更都可由任何具有數位參考的程式代碼觀察,如下列範例所示:

static void Main(string[] args)
{
    int[,] matrix = new int[2, 2];
    FillMatrix(matrix);
    // matrix is now full of -1
}

public static void FillMatrix(int[,] matrix)
{
    for (int i = 0; i < matrix.GetLength(0); i++)
    {
        for (int j = 0; j < matrix.GetLength(1); j++)
        {
            matrix[i, j] = -1;
        }
    }
}

非同步方法

使用非同步功能,您就可以呼叫非同步方法,而不需要使用明確回呼或手動將您的程式碼分散到多種方法或 lambda 運算式上。

如果您使用 async 修飾詞來標示方法,可以在方法中使用 await 運算子。 當控件到達異步方法中的 await 運算式時,控件會傳回給呼叫端,而且方法中的進度會暫停,直到等候的工作完成為止。 當工作完成時,方法中的執行可以繼續。

備註

非同步方法在遇到第一個尚未完成的等候物件時或當非同步方法結束時,會傳回呼叫端,以先發生者為準。

異步方法通常具有、 TaskIAsyncEnumerable<T>voidTask<TResult>傳回型別。 void 傳回型別主要用於定義需要 void 傳回型別的事件處理常式。 傳回 void 的非同步方法無法等候,而且 void 傳回方法的呼叫端無法攔截方法擲回的例外狀況。 非同步方法可具備任何類似 Task 的傳回類型

在下列範例中,DelayAsync 是具備 Task<TResult> 傳回型別的異步方法。 DelayAsync return具有傳回整數的語句。 因此,DelayAsync的方法宣告必須具有Task<int>的傳回型別。 因為傳回型別是Task<int>,在DoSomethingAsync中評估await表達式會產生整數,如下列語句所示:int result = await delayTask

方法 Main 是異步方法的範例,其傳回型別為 Task。 它會移至 DoSomethingAsync 方法,因為它以單行表示,因此可以省略 asyncawait 關鍵詞。 因為 DoSomethingAsync 是異步方法,因此必須等候呼叫 的工作 DoSomethingAsync ,如下列語句所示: await DoSomethingAsync();

class Program
{
    static Task Main() => DoSomethingAsync();

    static async Task DoSomethingAsync()
    {
        Task<int> delayTask = DelayAsync();
        int result = await delayTask;

        // The previous two statements may be combined into
        // the following statement.
        //int result = await DelayAsync();

        Console.WriteLine($"Result: {result}");
    }

    static async Task<int> DelayAsync()
    {
        await Task.Delay(100);
        return 5;
    }
}
// Example output:
//   Result: 5

異步方法無法宣告任何 refout 參數,但可以呼叫具有這類參數的方法。

如需非同步方法的詳細資訊,請參閱使用 async 和 await 進行非同步程式設計非同步傳回型別

表達式主體定義

在方法定義中,通常有的方法會直接利用運算式的結果立即返回,或者是以單一語句作為方法的主體。 定義這類方法時,使用=>可以使用語法快捷方式:

public Point Move(int dx, int dy) => new Point(x + dx, y + dy);
public void Print() => Console.WriteLine(First + " " + Last);
// Works with operators, properties, and indexers too.
public static Complex operator +(Complex a, Complex b) => a.Add(b);
public string Name => First + " " + Last;
public Customer this[long id] => store.LookupCustomer(id);

如果方法傳 void 回 或 是異步方法,則方法的主體必須是語句表達式(與 Lambda 相同)。 針對屬性和索引器,它們必須是唯讀的,且你不會使用 get 存取子關鍵字。

迭代器

迭代器會對集合執行自訂的反覆項目,例如清單或陣列。 迭代器會使用 yield return 陳述式,一次傳回一個項目。 當到達yield return語句時,會記住程式碼中的目前位置。 下次呼叫反覆運算器時,會從該位置重新啟動執行。

您可以使用 foreach 語句,從用戶端程式代碼呼叫反覆運算器。

迭代器的傳回型別可以是 IEnumerableIEnumerable<T>IAsyncEnumerable<T>IEnumeratorIEnumerator<T>

如需詳細資訊,請參閱 Iterator

C# 語言規格

如需詳細資訊,請參閱 C# 語言規格。 語言規格是 C# 語法和使用方式的最終來源。

另請參閱