宣告陳述式

宣告陳述式會宣告新的區域變數、區域常數或區域參考變數

C# 語言參考資料記錄了 C# 語言最新版本。 同時也包含即將推出語言版本公開預覽功能的初步文件。

文件中標示了語言最近三個版本或目前公開預覽版中首次引入的任何功能。

小提示

欲查詢某功能何時首次在 C# 中引入,請參閱 C# 語言版本歷史的條目。

若要宣告區域變數,請指定其型別並提供其名稱。 您可以如下列範例所示,在一個陳述式中宣告多個相同型別的變數:

string greeting;
int a, b, c;
List<double> xs;

在宣告陳述式中,您也可以使用其初始值來初始化變數:

string greeting = "Hello";
int a = 3, b = 2, c = a + b;
List<double> xs = new();

上述範例會明確指定變數的型別。 您也可以讓編譯器從其初始化運算式推斷變數的型別。 若要這樣做,請使用 var 關鍵字,而不是型別的名稱。 如需詳細資訊,請參閱隱含型別區域變數一節。

若要宣告區域常數,請如下列範例所示,使用 const 關鍵字

const string Greeting = "Hello";
const double MinLimit = -10.0, MaxLimit = -MinLimit;

當您宣告區域常數時,也必須將其初始化。

如需區域參考變數的相關資訊,請參閱參考變數一節。

隱含型別區域變數

當您宣告區域變數時,您可以讓編譯器從初始化運算式推斷變數的型別。 為此,請使用 var 關鍵字取代類型名稱:

var greeting = "Hello";
Console.WriteLine(greeting.GetType());  // output: System.String

var a = 32;
Console.WriteLine(a.GetType());  // output: System.Int32

var xs = new List<double>();
Console.WriteLine(xs.GetType());  // output: System.Collections.Generic.List`1[System.Double]

如前例所示,隱式型別的局部變數是強型別的。

注意

當您在啟用var中使用 ,而初始化運算式的型別是參考型別時,編譯器一律會推斷可為 Null 的參考型別,即使初始化運算式的型別不可為 Null 也一樣。

var 的常見用法是搭配建構函式叫用運算式。 使用 可以 var 避免在變數宣告和物件實例中重複型別名稱,如下範例所示:

var xs = new List<int>();

您可以使用目標型別new運算式作為替代方式:

List<int> xs = new();
List<int>? ys = new();

當你處理 匿名型態時,必須使用隱式型別的區域變數。 下列範例顯示使用匿名型別來保存客戶名稱和電話號碼的查詢運算式

var fromPhoenix = from cust in customers
                  where cust.City == "Phoenix"
                  select new { cust.Name, cust.Phone };

foreach (var customer in fromPhoenix)
{
    Console.WriteLine($"Name={customer.Name}, Phone={customer.Phone}");
}

在上述範例中,您無法明確指定 fromPhoenix 變數的型別。 此型別是 IEnumerable<T>,但在此案例中,T 是匿名型別,您無法提供其名稱。 這就是為什麼您需要使用 var。 基於相同的理由,您必須在 var 陳述式中宣告 customer 反覆運算變數時使用 foreach

欲了解更多隱式型別區域變數的資訊,請參見 隱式型別的局部變數

在模式比對中,var 關鍵字會用於 var 模式中。

參考變數

當您宣告區域變數並在變數型別之前新增 ref 關鍵字時,您會宣告參考變數ref local:

ref int aliasOfvariable = ref variable;

參考變數是參考另一個變數的變數,稱為參照。 也就是說,參考變數是其參照的別名。 當你指派一個參考變數值時,你就是把該值指派給該參考對象。 當你讀取參考變數的值時,你回傳的是該參考對象的值。 下列範例示範了該行為:

int a = 1;
ref int aliasOfa = ref a;
Console.WriteLine($"(a, aliasOfa) is ({a}, {aliasOfa})");  // output: (a, aliasOfa) is (1, 1)

a = 2;
Console.WriteLine($"(a, aliasOfa) is ({a}, {aliasOfa})");  // output: (a, aliasOfa) is (2, 2)

aliasOfa = 3;
Console.WriteLine($"(a, aliasOfa) is ({a}, {aliasOfa})");  // output: (a, aliasOfa) is (3, 3)

如下列範例所示,使用 ref 指派運算子= ref來變更參考變數的參照:

void Display(int[] s) => Console.WriteLine(string.Join(" ", s));

int[] xs = [0, 0, 0];
Display(xs);

ref int element = ref xs[0];
element = 1;
Display(xs);

element = ref xs[^1];
element = 3;
Display(xs);
// Output:
// 0 0 0
// 1 0 0
// 1 0 3

在上述範例中,會將 element 參考變數初始化為第一個陣列元素的別名。 然後其會 ref 重新指派以參考最後一個陣列元素。

您可以定義 ref readonly 區域變數。 您無法將值指派給 ref readonly 變數。 不過,你可以 ref 重新指派這樣的參考變數,如下範例所示:

int[] xs = [1, 2, 3];

ref readonly int element = ref xs[0];
// element = 100;  error CS0131: The left-hand side of an assignment must be a variable, property or indexer
Console.WriteLine(element);  // output: 1

element = ref xs[^1];
Console.WriteLine(element);  // output: 3

您可以如下列範例所示,將參考傳回指派給參考變數:

using System;

public class NumberStore
{
    private readonly int[] numbers = [1, 30, 7, 1557, 381, 63, 1027, 2550, 511, 1023];

    public ref int GetReferenceToMax()
    {
        ref int max = ref numbers[0];
        for (int i = 1; i < numbers.Length; i++)
        {
            if (numbers[i] > max)
            {
                max = ref numbers[i];
            }
        }
        return ref max;
    }

    public override string ToString() => string.Join(" ", numbers);
}

public static class ReferenceReturnExample
{
    public static void Run()
    {
        var store = new NumberStore();
        Console.WriteLine($"Original sequence: {store.ToString()}");
        
        ref int max = ref store.GetReferenceToMax();
        max = 0;
        Console.WriteLine($"Updated sequence:  {store.ToString()}");
        // Output:
        // Original sequence: 1 30 7 1557 381 63 1027 2550 511 1023
        // Updated sequence:  1 30 7 1557 381 63 1027 0 511 1023
    }
}

在上述範例中,GetReferenceToMax 方法是 returns-by-ref 方法。 其不會傳回最大值本身,但參考傳回是保存最大值之陣列元素的別名。 Run 方法會將參考傳回指派給 max 參考變數。 然後,藉由指派給 max,其會更新 store 執行個體的內部記憶體。 您也可以定義 ref readonly 方法。 ref readonly 方法的呼叫端無法將值指派給其參考傳回。

foreach 陳述式的反覆運算變數可以是參考變數。 如需詳細資訊,請參閱foreach一文的陳述式一節。

在效能關鍵情節中,使用參考變數和傳回可以藉由避免成本高昂的複製作業來提升效能。

編譯器可確保參考變數的存留期不會比其參考更長,並在整個存留期內保持有效。 如需詳細資訊,請參閱 C# 語言規格Ref 安全內容一節。

如需 ref 欄位的相關資訊,請參閱ref結構類型文章的 ref 欄位一節。

限定範圍 ref

內容關鍵字 scoped 會限制值的存留期。 scoped 修飾元會將 ref-safe-to-escapesafe-to-escape 存留期分別限制為目前方法。 加入 scoped 修飾符後,你宣稱你的程式碼並未延長變數的壽命。

套用 scoped 參數或區域變數。 當型別為 ref struct時,你可以對參數和本地值套用scoped修飾符。 否則,修飾符只套用 scoped 於局部 參考變數。 該規則包含以 ref 修飾符宣告的本地變數,以及以 inrefout 修飾符宣告的參數。

類型為 scoped 時,this 修飾元會隱含地新增至 struct 中所宣告方法內的 outref 參數和 ref struct 參數。

C# 語言規格

如需詳細資訊,請參閱 C# 語言規格的下列幾節:

如需 scoped 修飾元的詳細資訊,請參閱低階結構改善提案注意事項。

另請參閱