內建參考型別 (C# 參考)Built-in reference types (C# reference)

C# 有數種內建參考型別。C# has a number of built-in reference types. 它們具有關鍵字或運算子,是 .NET 程式庫中類型的同義字。They have keywords or operators that are synonyms for a type in the .NET library.

物件型別The object type

object 類型是 System.Object 在 .NET 中的別名。The object type is an alias for System.Object in .NET. 在 C# 的統一型別系統中,所有類型 (預先定義和使用者定義的、參考型別和實值型別) 都會直接或間接繼承自 System.ObjectIn the unified type system of C#, all types, predefined and user-defined, reference types and value types, inherit directly or indirectly from System.Object. 您可以將任何型別的值指派給 object 型別的變數。You can assign values of any type to variables of type object. 任何 object 變數都可以使用常值 null 指派給其預設值。Any object variable can be assigned to its default value using the literal null. 當實值型別的變數轉換成物件時,即稱之為 BoxedWhen a variable of a value type is converted to object, it is said to be boxed. 當型別的變數轉換成實 object 值型別時,就表示它是取消 裝箱When a variable of type object is converted to a value type, it is said to be unboxed. 如需詳細資訊,請參閱 Boxing 和 UnboxingFor more information, see Boxing and Unboxing.

字串型別The string type

string 類型代表零或多個 Unicode 字元序列。The string type represents a sequence of zero or more Unicode characters. stringSystem.String 在 .NET 中的別名。string is an alias for System.String in .NET.

雖然 string 是參考型別,但是會定義等號比較運算子 ==!= 來比較 string 物件的值,而不是參考。Although string is a reference type, the equality operators == and != are defined to compare the values of string objects, not references. 這樣會以更直覺的方式來測試字串是否相等。This makes testing for string equality more intuitive. 例如:For example:

string a = "hello";
string b = "h";
// Append to contents of 'b'
b += "ello";
Console.WriteLine(a == b);
Console.WriteLine(object.ReferenceEquals(a, b));

這會依序顯示 "True" 和 "False",因為字串的內容相等,但 ab 未參照相同的字串執行個體。This displays "True" and then "False" because the content of the strings are equivalent, but a and b do not refer to the same string instance.

+ 運算子會串連字串:The + operator concatenates strings:

string a = "good " + "morning";

這會建立包含 "good morning" 的字串物件。This creates a string object that contains "good morning".

字串是「不可變的」**;在建立物件之後,就無法變更字串物件的內容,雖然語法讓它看起來就像您可以這麼做一樣。Strings are immutable--the contents of a string object cannot be changed after the object is created, although the syntax makes it appear as if you can do this. 例如,當您撰寫此程式碼時,編譯器實際上會建立新的字串物件,以保存新序列的字元,並且會將新物件指派給 bFor example, when you write this code, the compiler actually creates a new string object to hold the new sequence of characters, and that new object is assigned to b. 已配置給 b 的記憶體 (當其包含字串 "h" 時) 即適用於記憶體回收。The memory that had been allocated for b (when it contained the string "h") is then eligible for garbage collection.

string b = "h";
b += "ello";

[]運算子可用於唯讀存取字串的個別字元。The [] operator can be used for readonly access to individual characters of a string. 有效的索引值從開始 0 ,而且必須小於字串的長度:Valid index values start at 0 and must be less than the length of the string:

string str = "test";
char x = str[2];  // x = 's';

以類似的方式, [] 運算子也可以用來逐一查看字串中的每個字元:In similar fashion, the [] operator can also be used for iterating over each character in a string:

string str = "test";

for (int i = 0; i < str.Length; i++)
{
  Console.Write(str[i] + " ");
}
// Output: t e s t

字串常值的型別是 string,可以撰寫為兩種形式:quoted 和 @-quoted。String literals are of type string and can be written in two forms, quoted and @-quoted. 以引號括住的字串常值是以雙引號 (") 括住:Quoted string literals are enclosed in double quotation marks ("):

"good morning"  // a string literal

字串常值可以包含任何字元常值。String literals can contain any character literal. 包含逸出序列。Escape sequences are included. 下列範例使用逸出序列 \\ 表示反斜線、\u0066 表示字母 f,而 \n 表示新行字元。The following example uses escape sequence \\ for backslash, \u0066 for the letter f, and \n for newline.

string a = "\\\u0066\n F";
Console.WriteLine(a);
// Output:
// \f
//  F

注意

逸出代碼 \udddd (其中 dddd 是四位數字) 代表 Unicode 字元 U+ddddThe escape code \udddd (where dddd is a four-digit number) represents the Unicode character U+dddd. 也會辨識八位數 Unicode 逸出代碼︰\UddddddddEight-digit Unicode escape codes are also recognized: \Udddddddd.

逐字字串常值的開頭為 @,也會用雙引號括住。Verbatim string literals start with @ and are also enclosed in double quotation marks. 例如:For example:

@"good morning"  // a string literal

逐字字串的優點是「不會」** 處理逸出序列,例如,這可讓您輕鬆地撰寫完整 Windows 檔案名稱︰The advantage of verbatim strings is that escape sequences are not processed, which makes it easy to write, for example, a fully qualified Windows file name:

@"c:\Docs\Source\a.txt"  // rather than "c:\\Docs\\Source\\a.txt"

若要在 @-quoted 字串中包含雙引號,請使用兩個雙引號︰To include a double quotation mark in an @-quoted string, double it:

@"""Ahoy!"" cried the captain." // "Ahoy!" cried the captain.

委派型別The delegate type

委派類型的宣告類似方法簽章。The declaration of a delegate type is similar to a method signature. 它具有傳回值以及任意類型之任何數目的參數:It has a return value and any number of parameters of any type:

public delegate void MessageDelegate(string message);
public delegate int AnotherDelegate(MyType m, long num);

在 .NET 中,System.ActionSystem.Func 型別提供許多常見委派的泛型定義。In .NET, System.Action and System.Func types provide generic definitions for many common delegates. 您多半不需要定義新的自訂委派型別。You likely don't need to define new custom delegate types. 反之,您可以建立所提供之泛型型別的具現化。Instead, you can create instantiations of the provided generic types.

delegate 是可用來封裝具名或匿名方法的參考型別。A delegate is a reference type that can be used to encapsulate a named or an anonymous method. 委派類似 C++ 中的函式指標,但委派是型別安全而且安全的。Delegates are similar to function pointers in C++; however, delegates are type-safe and secure. 如需委派的應用程式,請參閱委派泛型委派For applications of delegates, see Delegates and Generic Delegates. 委派是事件的基礎。Delegates are the basis for Events. 委派的具現化方式是將它與具名或匿名方法建立關聯。A delegate can be instantiated by associating it either with a named or anonymous method.

委派必須使用具有相容傳回型別和輸入參數的方法或 Lambda 運算式進行具現化。The delegate must be instantiated with a method or lambda expression that has a compatible return type and input parameters. 如需方法簽章中所允許變異程度的詳細資訊,請參閱 Variance in Delegates (委派中的變異數)。For more information on the degree of variance that is allowed in the method signature, see Variance in Delegates. 若與匿名方法搭配使用,則會一起宣告要與它建立關聯的委派和程式碼。For use with anonymous methods, the delegate and the code to be associated with it are declared together.

動態型別The dynamic type

dynamic 型別指出使用變數和對其成員的參考,會略過編譯時間型別檢查。The dynamic type indicates that use of the variable and references to its members bypass compile-time type checking. 相反地,這些作業會在執行階段解決。Instead, these operations are resolved at run time. dynamic 類型會簡化 Office Automation API 這類 COM API 的存取、IronPython 程式庫這類動態 API 的存取,以及 HTML 文件物件模型 (DOM) 的存取。The dynamic type simplifies access to COM APIs such as the Office Automation APIs, to dynamic APIs such as IronPython libraries, and to the HTML Document Object Model (DOM).

在大多數情況下,dynamic 類型的行為與 object 類型類似。Type dynamic behaves like type object in most circumstances. 特別是,任何非 Null 運算式都可轉換成 dynamic 型別。In particular, any non-null expression can be converted to the dynamic type. dynamic 型別與 object 的不同之處在於,包含型別 dynamic 運算式的操作,不會由編譯器解析或進行型別檢查。The dynamic type differs from object in that operations that contain expressions of type dynamic are not resolved or type checked by the compiler. 編譯器會將作業資訊封裝在一起,而且稍後在執行階段會使用這項資訊來評估作業。The compiler packages together information about the operation, and that information is later used to evaluate the operation at run time. 在此程序期間,會將 dynamic 類型的變數編譯為 object 類型的變數。As part of the process, variables of type dynamic are compiled into variables of type object. 因此,dynamic 類型只存在於編譯時期,而非執行階段。Therefore, type dynamic exists only at compile time, not at run time.

下列範例會對照 dynamic 類型的變數與 object 類型的變數。The following example contrasts a variable of type dynamic to a variable of type object. 若要在編譯時期驗證每個變數的類型,請將滑鼠指標放在 WriteLine 陳述式中的 dynobj 上方。To verify the type of each variable at compile time, place the mouse pointer over dyn or obj in the WriteLine statements. 將下列程式碼複製到可使用 IntelliSense 的編輯器。Copy the following code into an editor where IntelliSense is available. IntelliSense 會顯示「動態」**** 來表示 dyn,並顯示「物件」**** 來表示 objIntelliSense shows dynamic for dyn and object for obj.

class Program
{
    static void Main(string[] args)
    {
        dynamic dyn = 1;
        object obj = 1;

        // Rest the mouse pointer over dyn and obj to see their
        // types at compile time.
        System.Console.WriteLine(dyn.GetType());
        System.Console.WriteLine(obj.GetType());
    }
}

WriteLine 陳述式會顯示執行階段類型 dynobjThe WriteLine statements display the run-time types of dyn and obj. 此時,兩者都有相同的類型:整數。At that point, both have the same type, integer. 此時會產生下列輸出:The following output is produced:

System.Int32
System.Int32

若要查看 dynobj 在編譯時期的差異,請在上述範例的宣告與 WriteLine 陳述式之間新增下列兩行。To see the difference between dyn and obj at compile time, add the following two lines between the declarations and the WriteLine statements in the previous example.

dyn = dyn + 3;
obj = obj + 3;

嘗試新增運算式 obj + 3 中的整數和物件時報告編譯器錯誤。A compiler error is reported for the attempted addition of an integer and an object in expression obj + 3. 不過,不會回報 dyn + 3 的錯誤。However, no error is reported for dyn + 3. 在編譯時期不會檢查包含 dyn 的運算式,因為 dyn 的類型是 dynamicThe expression that contains dyn is not checked at compile time because the type of dyn is dynamic.

下列範例會在數個宣告中使用 dynamicThe following example uses dynamic in several declarations. Main 方法也會對照編譯時期類型檢查與執行階段類型檢查。The Main method also contrasts compile-time type checking with run-time type checking.

using System;

namespace DynamicExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            ExampleClass ec = new ExampleClass();
            Console.WriteLine(ec.exampleMethod(10));
            Console.WriteLine(ec.exampleMethod("value"));

            // The following line causes a compiler error because exampleMethod
            // takes only one argument.
            //Console.WriteLine(ec.exampleMethod(10, 4));

            dynamic dynamic_ec = new ExampleClass();
            Console.WriteLine(dynamic_ec.exampleMethod(10));

            // Because dynamic_ec is dynamic, the following call to exampleMethod
            // with two arguments does not produce an error at compile time.
            // However, it does cause a run-time error.
            //Console.WriteLine(dynamic_ec.exampleMethod(10, 4));
        }
    }

    class ExampleClass
    {
        static dynamic field;
        dynamic prop { get; set; }

        public dynamic exampleMethod(dynamic d)
        {
            dynamic local = "Local variable";
            int two = 2;

            if (d is int)
            {
                return local;
            }
            else
            {
                return two;
            }
        }
    }
}
// Results:
// Local variable
// 2
// Local variable

另請參閱See also