型別Types

C#語言的類型分成兩個主要類別:實數值型別參考型別The types of the C# language are divided into two main categories: value types and reference types. 實數值型別和參考型別都可以是泛型型別,這會採用一或多個類型參數Both value types and reference types may be generic types, which take one or more type parameters. 類型參數可以同時指定實數值型別和參考型別。Type parameters can designate both value types and reference types.

type
    : value_type
    | reference_type
    | type_parameter
    | type_unsafe
    ;

類型、指標的最終分類僅適用于 unsafe 程式碼。The final category of types, pointers, is available only in unsafe code. 這會在指標類型中進一步討論。This is discussed further in Pointer types.

實值型別與參考型別不同的是,實值型別的變數會直接包含其資料,而參考型別的變數則會儲存其資料的參考,後者又稱為物件Value types differ from reference types in that variables of the value types directly contain their data, whereas variables of the reference types store references to their data, the latter being known as objects. 有了參考型別,兩個變數都可以參考相同的物件,因此在某個變數上的作業可能會影響另一個變數所參考的物件。With reference types, it is possible for two variables to reference the same object, and thus possible for operations on one variable to affect the object referenced by the other variable. 使用實值型別時,每個變數都有自己的資料複本,而且其中一個的作業不可能影響另一個。With value types, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other.

C#的類型系統是統一的,因此可以將任何類型的值視為物件。C#'s type system is unified such that a value of any type can be treated as an object. C# 中的每個型別都直接或間接衍生自 object 類別型別,而 object 是所有型別的基底類別。Every type in C# directly or indirectly derives from the object class type, and object is the ultimate base class of all types. 參考型別的值之所以會視為物件,只是將這些值當作 object 型別來檢視。Values of reference types are treated as objects simply by viewing the values as type object. 實數值型別的值會藉由執行裝箱和取消裝箱作業(裝箱和取消裝箱)來視為物件。Values of value types are treated as objects by performing boxing and unboxing operations (Boxing and unboxing).

值類型Value types

實值型別可以是結構型別或列舉型別。A value type is either a struct type or an enumeration type. C#提供一組稱為簡單類型的預先定義結構類型。C# provides a set of predefined struct types called the simple types. 簡單類型是透過保留字來識別。The simple types are identified through reserved words.

value_type
    : struct_type
    | enum_type
    ;

struct_type
    : type_name
    | simple_type
    | nullable_type
    ;

simple_type
    : numeric_type
    | 'bool'
    ;

numeric_type
    : integral_type
    | floating_point_type
    | 'decimal'
    ;

integral_type
    : 'sbyte'
    | 'byte'
    | 'short'
    | 'ushort'
    | 'int'
    | 'uint'
    | 'long'
    | 'ulong'
    | 'char'
    ;

floating_point_type
    : 'float'
    | 'double'
    ;

nullable_type
    : non_nullable_value_type '?'
    ;

non_nullable_value_type
    : type
    ;

enum_type
    : type_name
    ;

不同于參考型別的變數,實數值型別的變數只有在實數值型別是可為 null 的類型時,才可以包含值 nullUnlike a variable of a reference type, a variable of a value type can contain the value null only if the value type is a nullable type. 針對每一個不可為 null 的實數值型別,有一個對應的可為 null 實數值型別,表示相同的值集加上 null的值。For every non-nullable value type there is a corresponding nullable value type denoting the same set of values plus the value null.

指派至實數值型別的變數會建立所指派值的複本。Assignment to a variable of a value type creates a copy of the value being assigned. 這與指派給參考型別的變數不同,後者會複製參考,而不是參考所識別的物件。This differs from assignment to a variable of a reference type, which copies the reference but not the object identified by the reference.

System.object 類型The System.ValueType type

所有實值型別都會隱含繼承自類別 System.ValueType,而這又繼承自類別 objectAll value types implicitly inherit from the class System.ValueType, which, in turn, inherits from class object. 任何類型都無法衍生自實數值型別,而實數值型別因此隱含密封(密封類別)。It is not possible for any type to derive from a value type, and value types are thus implicitly sealed (Sealed classes).

請注意,System.ValueType 本身並不是value_typeNote that System.ValueType is not itself a value_type. 相反地,它是自動衍生所有value_typeclass_typeRather, it is a class_type from which all value_types are automatically derived.

預設建構函式Default constructors

所有實值型別會隱含地宣告一個稱為預設的函式的公用無參數實例的函數。All value types implicitly declare a public parameterless instance constructor called the default constructor. 預設的函式會傳回零初始化的實例,稱為實數值型別的預設值The default constructor returns a zero-initialized instance known as the default value for the value type:

  • 針對所有simple_types,預設值為所有零的位模式所產生的值:For all simple_types, the default value is the value produced by a bit pattern of all zeros:
    • 針對 sbytebyteshortushortintuintlongulong,預設值為 [0]。For sbyte, byte, short, ushort, int, uint, long, and ulong, the default value is 0.
    • 針對 char,預設值為 '\x0000'For char, the default value is '\x0000'.
    • 針對 float,預設值為 0.0fFor float, the default value is 0.0f.
    • 針對 double,預設值為 0.0dFor double, the default value is 0.0d.
    • 針對 decimal,預設值為 0.0mFor decimal, the default value is 0.0m.
    • 針對 bool,預設值為 falseFor bool, the default value is false.
  • 針對enum_type E,預設值為 0,轉換為類型 EFor an enum_type E, the default value is 0, converted to the type E.
  • 對於struct_type,預設值是將所有實值型別字段設定為其預設值,以及要 null的所有參考型別字段所產生的值。For a struct_type, the default value is the value produced by setting all value type fields to their default value and all reference type fields to null.
  • 對於nullable_type ,預設值是 HasValue 屬性為 false 且未定義 Value 屬性的實例。For a nullable_type the default value is an instance for which the HasValue property is false and the Value property is undefined. 預設值也稱為可為 null 類型的null 值The default value is also known as the null value of the nullable type.

就像任何其他實例的函式一樣,實值型別的預設的函數會使用 new 運算子來叫用。Like any other instance constructor, the default constructor of a value type is invoked using the new operator. 基於效率的考慮,這項需求並不是要實際讓執行產生一個函式呼叫。For efficiency reasons, this requirement is not intended to actually have the implementation generate a constructor call. 在下列範例中,ij 的變數都會初始化為零。In the example below, variables i and j are both initialized to zero.

class A
{
    void F() {
        int i = 0;
        int j = new int();
    }
}

由於每個實數值型別都隱含具有公用無參數實例的函式,因此結構類型不可能包含無參數之函數的明確宣告。Because every value type implicitly has a public parameterless instance constructor, it is not possible for a struct type to contain an explicit declaration of a parameterless constructor. 不過,結構類型允許宣告參數化實例的函式(函式)。A struct type is however permitted to declare parameterized instance constructors (Constructors).

結構型別Struct types

結構類型是實數值型別,可以宣告常數、欄位、方法、屬性、索引子、運算子、實例的函式、靜態的函式和巢狀型別。A struct type is a value type that can declare constants, fields, methods, properties, indexers, operators, instance constructors, static constructors, and nested types. 結構類型的宣告會在結構宣告中說明。The declaration of struct types is described in Struct declarations.

簡單型別Simple types

C#提供一組稱為簡單類型的預先定義結構類型。C# provides a set of predefined struct types called the simple types. 簡單類型是透過保留字來識別,但這些保留字只是 System 命名空間中預先定義結構類型的別名,如下表所述。The simple types are identified through reserved words, but these reserved words are simply aliases for predefined struct types in the System namespace, as described in the table below.

保留字Reserved word 別名類型Aliased type
sbyte System.SByte
byte System.Byte
short System.Int16
ushort System.UInt16
int System.Int32
uint System.UInt32
long System.Int64
ulong System.UInt64
char System.Char
float System.Single
double System.Double
bool System.Boolean
decimal System.Decimal

因為簡單型別會將結構型別做為別名,所以每個簡單型別都有成員。Because a simple type aliases a struct type, every simple type has members. 例如,int 具有在 System.Int32 中宣告的成員,以及繼承自 System.Object的成員,且允許下列語句:For example, int has the members declared in System.Int32 and the members inherited from System.Object, and the following statements are permitted:

int i = int.MaxValue;           // System.Int32.MaxValue constant
string s = i.ToString();        // System.Int32.ToString() instance method
string t = 123.ToString();      // System.Int32.ToString() instance method

簡單型別與其他結構型別的差異在於它們可允許某些額外的作業:The simple types differ from other struct types in that they permit certain additional operations:

  • 大部分的簡單類型都允許藉由撰寫值(值)來建立值。Most simple types permit values to be created by writing literals (Literals). 例如,123int 類型的常值,而 'a'char類型的常值。For example, 123 is a literal of type int and 'a' is a literal of type char. C#一般不會布建結構類型的常值,而且其他結構類型的非預設值最後一律會透過這些結構類型的實例構造函式來建立。C# makes no provision for literals of struct types in general, and non-default values of other struct types are ultimately always created through instance constructors of those struct types.
  • 當運算式的運算元都是簡單類型常數時,編譯器可以在編譯時期評估運算式。When the operands of an expression are all simple type constants, it is possible for the compiler to evaluate the expression at compile-time. 這類運算式稱為constant_expression常數運算式)。Such an expression is known as a constant_expression (Constant expressions). 涉及其他結構類型所定義之運算子的運算式,不會被視為常數運算式。Expressions involving operators defined by other struct types are not considered to be constant expressions.
  • 透過 const 宣告,可以宣告簡單類型(常數)的常數。Through const declarations it is possible to declare constants of the simple types (Constants). 不可能有其他結構類型的常數,但 static readonly 欄位會提供類似的效果。It is not possible to have constants of other struct types, but a similar effect is provided by static readonly fields.
  • 包含簡單類型的轉換可以參與評估其他結構類型所定義的轉換運算子,但使用者定義的轉換運算子不能參與其他使用者定義運算子的評估(評估使用者定義的轉換)。Conversions involving simple types can participate in evaluation of conversion operators defined by other struct types, but a user-defined conversion operator can never participate in evaluation of another user-defined operator (Evaluation of user-defined conversions).

整數類資料型別Integral types

C#支援九種整數類型: sbytebyteshortushortintuintlongulongcharC# supports nine integral types: sbyte, byte, short, ushort, int, uint, long, ulong, and char. 整數類資料類型具有下列大小和範圍的值:The integral types have the following sizes and ranges of values:

  • sbyte 類型代表帶正負號的8位整數,其值介於-128 和127之間。The sbyte type represents signed 8-bit integers with values between -128 and 127.
  • byte 類型代表不帶正負號的8位整數,其值介於0到255之間。The byte type represents unsigned 8-bit integers with values between 0 and 255.
  • short 類型代表帶正負號的16位整數,其值介於-32768 和32767之間。The short type represents signed 16-bit integers with values between -32768 and 32767.
  • ushort 類型代表不帶正負號的16位整數,其值介於0到65535之間。The ushort type represents unsigned 16-bit integers with values between 0 and 65535.
  • int 類型代表帶正負號的32位整數,其值介於-2147483648 與2147483647之間。The int type represents signed 32-bit integers with values between -2147483648 and 2147483647.
  • uint 類型代表不帶正負號的32位整數,其值介於0到4294967295之間。The uint type represents unsigned 32-bit integers with values between 0 and 4294967295.
  • long 類型代表帶正負號的64位整數,其值介於-9223372036854775808 到9223372036854775807之間。The long type represents signed 64-bit integers with values between -9223372036854775808 and 9223372036854775807.
  • ulong 類型代表不帶正負號的64位整數,其值介於0到18446744073709551615之間。The ulong type represents unsigned 64-bit integers with values between 0 and 18446744073709551615.
  • char 類型代表不帶正負號的16位整數,其值介於0到65535之間。The char type represents unsigned 16-bit integers with values between 0 and 65535. char 類型的可能值集合會對應到 Unicode 字元集。The set of possible values for the char type corresponds to the Unicode character set. 雖然 charushort有相同的標記法,但不允許在另一個類型上允許所有作業。Although char has the same representation as ushort, not all operations permitted on one type are permitted on the other.

整數類型的一元和二元運算子一律會使用帶正負號的32位有效位數、不帶正負號的32位精確度、帶正負號的64位有效位數或不帶正負號的64位有效位數來運作:The integral-type unary and binary operators always operate with signed 32-bit precision, unsigned 32-bit precision, signed 64-bit precision, or unsigned 64-bit precision:

  • 對於一元 +~ 運算子而言,運算元會轉換成類型 T,其中 Tintuintlongulong 的第一個,可以完全表示運算元的所有可能值。For the unary + and ~ operators, the operand is converted to type T, where T is the first of int, uint, long, and ulong that can fully represent all possible values of the operand. 接著會使用 T類型的有效位數來執行作業,並 T結果的類型。The operation is then performed using the precision of type T, and the type of the result is T.
  • 針對一元 - 運算子,運算元會轉換成類型 T,其中 T 是可以完全代表運算元所有可能值的 intlong 的第一個。For the unary - operator, the operand is converted to type T, where T is the first of int and long that can fully represent all possible values of the operand. 接著會使用 T類型的有效位數來執行作業,並 T結果的類型。The operation is then performed using the precision of type T, and the type of the result is T. 一元 - 運算子不能套用至 ulong類型的運算元。The unary - operator cannot be applied to operands of type ulong.
  • 針對二進位 +-*/%&^|==!=><>=<= 運算子會將運算元轉換成類型 T,其中 Tintuintlongulong 的第一個,可以完全表示這兩個運算元的所有可能值。For the binary +, -, *, /, %, &, ^, |, ==, !=, >, <, >=, and <= operators, the operands are converted to type T, where T is the first of int, uint, long, and ulong that can fully represent all possible values of both operands. 然後,會使用 T類型的有效位數來執行作業,而結果的類型會是 T (或關聯式運算子的 bool)。The operation is then performed using the precision of type T, and the type of the result is T (or bool for the relational operators). 一個運算元不允許 long 類型,另一個則屬於 ulong 與二元運算子的類型。It is not permitted for one operand to be of type long and the other to be of type ulong with the binary operators.
  • 針對二元 <<>> 運算子,左運算元會轉換成類型 T,其中 Tintuintlongulong 的第一個,可以完全表示運算元的所有可能值。For the binary << and >> operators, the left operand is converted to type T, where T is the first of int, uint, long, and ulong that can fully represent all possible values of the operand. 接著會使用 T類型的有效位數來執行作業,並 T結果的類型。The operation is then performed using the precision of type T, and the type of the result is T.

char 類型會分類為整數類資料類型,但它與其他整數類型不同,有兩種方式:The char type is classified as an integral type, but it differs from the other integral types in two ways:

  • 沒有從其他類型到 char 類型的隱含轉換。There are no implicit conversions from other types to the char type. 特別的是,即使 sbytebyteushort 類型的值範圍,都可以使用 char 類型來完整顯示,但是從 sbytebyteushortchar 的隱含轉換並不存在。In particular, even though the sbyte, byte, and ushort types have ranges of values that are fully representable using the char type, implicit conversions from sbyte, byte, or ushort to char do not exist.
  • char 類型的常數必須寫成character_literals 或integer_literals,並結合轉換成類型 charConstants of the char type must be written as character_literals or as integer_literals in combination with a cast to type char. 例如,(char)10'\x000A' 相同。For example, (char)10 is the same as '\x000A'.

checkedunchecked 運算子和語句是用來控制整數型別算數運算和轉換(checked 和 unchecked 運算子)的溢位檢查。The checked and unchecked operators and statements are used to control overflow checking for integral-type arithmetic operations and conversions (The checked and unchecked operators). checked 內容中,溢位會產生編譯時期錯誤,或導致 System.OverflowException 擲回。In a checked context, an overflow produces a compile-time error or causes a System.OverflowException to be thrown. unchecked 內容中,會忽略溢位,而且不會捨棄任何不符合目的地類型的高序位位。In an unchecked context, overflows are ignored and any high-order bits that do not fit in the destination type are discarded.

浮點類型Floating point types

C#支援兩種浮點類型: floatdoubleC# supports two floating point types: float and double. floatdouble 類型會使用32位單精確度和64位雙精確度 IEEE 754 格式來表示,這會提供下列集合的值:The float and double types are represented using the 32-bit single-precision and 64-bit double-precision IEEE 754 formats, which provide the following sets of values:

  • 正零和負零。Positive zero and negative zero. 在大部分情況下,正零和負零的行為與簡單值零相同,但是某些作業會區分兩個(除法運算子)。In most situations, positive zero and negative zero behave identically as the simple value zero, but certain operations distinguish between the two (Division operator).
  • 正無限大和負無限大。Positive infinity and negative infinity. 無限大是由這類作業所產生,會將非零的數位零除。Infinities are produced by such operations as dividing a non-zero number by zero. 例如,1.0 / 0.0 產生正無限大,-1.0 / 0.0 產生負無限大。For example, 1.0 / 0.0 yields positive infinity, and -1.0 / 0.0 yields negative infinity.
  • 非數位值,通常是 NaN 縮寫。The Not-a-Number value, often abbreviated NaN. Nan 是由不正確浮點運算所產生,例如零除零。NaNs are produced by invalid floating-point operations, such as dividing zero by zero.
  • 表單 s * m * 2^e的有限非零值集合,其中 s 為1或-1,而 me 是由特定的浮點類型所決定: float0 < m < 2^24-149 <= e <= 104``double0 < m < 2^53-1075 <= e <= 970的、和。The finite set of non-zero values of the form s * m * 2^e, where s is 1 or -1, and m and e are determined by the particular floating-point type: For float, 0 < m < 2^24 and -149 <= e <= 104, and for double, 0 < m < 2^53 and -1075 <= e <= 970. 不正規化的浮點數會被視為有效的非零值。Denormalized floating-point numbers are considered valid non-zero values.

float 類型可以代表範圍從大約 1.5 * 10^-453.4 * 10^38,精確度為7位數的值。The float type can represent values ranging from approximately 1.5 * 10^-45 to 3.4 * 10^38 with a precision of 7 digits.

double 類型可以代表範圍從大約 5.0 * 10^-3241.7 × 10^308,精確度為15-16 位數的值。The double type can represent values ranging from approximately 5.0 * 10^-324 to 1.7 × 10^308 with a precision of 15-16 digits.

如果二元運算子的其中一個運算元屬於浮點類型,則另一個運算元必須是整數類資料類型或浮點類型,而運算的評估方式如下:If one of the operands of a binary operator is of a floating-point type, then the other operand must be of an integral type or a floating-point type, and the operation is evaluated as follows:

  • 如果其中一個運算元是整數類資料類型,則該運算元會轉換成另一個運算元的浮點類型。If one of the operands is of an integral type, then that operand is converted to the floating-point type of the other operand.
  • 然後,如果任一個運算元的類型是 double,另一個運算元會轉換成 double,則會使用至少 double 範圍和有效位數來執行作業,而結果的類型會是 double (或 bool 關係運算子)。Then, if either of the operands is of type double, the other operand is converted to double, the operation is performed using at least double range and precision, and the type of the result is double (or bool for the relational operators).
  • 否則,會使用至少 float 的範圍和精確度來執行作業,而結果的類型會是 float (或關聯式運算子的 bool)。Otherwise, the operation is performed using at least float range and precision, and the type of the result is float (or bool for the relational operators).

浮點運算子(包括指派運算子)永遠不會產生例外狀況。The floating-point operators, including the assignment operators, never produce exceptions. 相反地,在例外狀況下,浮點運算會產生零、無限大或 NaN,如下所述:Instead, in exceptional situations, floating-point operations produce zero, infinity, or NaN, as described below:

  • 如果浮點運算的結果太小而無法用於目的地格式,作業的結果就會變成正零或負零。If the result of a floating-point operation is too small for the destination format, the result of the operation becomes positive zero or negative zero.
  • 如果浮點運算的結果對目的地格式而言太大,則作業的結果會變成正無限大或負無限大。If the result of a floating-point operation is too large for the destination format, the result of the operation becomes positive infinity or negative infinity.
  • 如果浮點運算無效,作業的結果就會變成 NaN。If a floating-point operation is invalid, the result of the operation becomes NaN.
  • 如果浮點運算的一個或兩個運算元都是 NaN,則作業的結果會變成 NaN。If one or both operands of a floating-point operation is NaN, the result of the operation becomes NaN.

執行浮點運算時,精確度可能會高於作業的結果類型。Floating-point operations may be performed with higher precision than the result type of the operation. 例如,某些硬體架構支援「延伸」或「長雙精度」浮點類型,其範圍和有效位數大於 double 類型,並使用這個較高的精確度類型來隱含執行所有浮點運算。For example, some hardware architectures support an "extended" or "long double" floating-point type with greater range and precision than the double type, and implicitly perform all floating-point operations using this higher precision type. 只有在效能過高的情況下,才能夠以較低的精確度執行浮點運算,而不需要實作為要略過效能和精確度的實體系, C#而是允許更高的精確度類型用於所有浮點運算。Only at excessive cost in performance can such hardware architectures be made to perform floating-point operations with less precision, and rather than require an implementation to forfeit both performance and precision, C# allows a higher precision type to be used for all floating-point operations. 除了提供更精確的結果,這種情況很少會有任何明顯的影響。Other than delivering more precise results, this rarely has any measurable effects. 不過,在表單 x * y / z的運算式中,乘法會產生超出 double 範圍的結果,但後續的除法會將暫存結果重新帶入 double 範圍,這是運算式在中評估的事實。較高的範圍格式可能會導致產生有限的結果,而不是無限大。However, in expressions of the form x * y / z, where the multiplication produces a result that is outside the double range, but the subsequent division brings the temporary result back into the double range, the fact that the expression is evaluated in a higher range format may cause a finite result to be produced instead of an infinity.

Decimal 類型The decimal type

decimal 型別是 128 位元的資料型別,適合財務和貨幣計算。The decimal type is a 128-bit data type suitable for financial and monetary calculations. decimal 類型可以代表範圍從 1.0 * 10^-28 到大約 7.9 * 10^28 28-29 個有效位數的值。The decimal type can represent values ranging from 1.0 * 10^-28 to approximately 7.9 * 10^28 with 28-29 significant digits.

decimal 類型的一組有限值的格式為 (-1)^s * c * 10^-e,其中的正負號 s 為0或1,c 是由 0 <= *c* < 2^96指定,而尺規 e 則是 0 <= e <= 28decimal 類型不支援帶正負號的零、無限大或 NaN。The finite set of values of type decimal are of the form (-1)^s * c * 10^-e, where the sign s is 0 or 1, the coefficient c is given by 0 <= *c* < 2^96, and the scale e is such that 0 <= e <= 28.The decimal type does not support signed zeros, infinities, or NaN's. decimal 是以10的乘冪來表示的96位整數。A decimal is represented as a 96-bit integer scaled by a power of ten. 針對絕對值小於 1.0mdecimals,此值會精確到28個小數位數,但不會再進一步。For decimals with an absolute value less than 1.0m, the value is exact to the 28th decimal place, but no further. 針對絕對值大於或等於 1.0mdecimals,此值會精確為28或29個數字。For decimals with an absolute value greater than or equal to 1.0m, the value is exact to 28 or 29 digits. 相反于 floatdouble 的資料類型,十進位的小數數位,例如0.1,可以完全在 decimal 標記法中表示。Contrary to the float and double data types, decimal fractional numbers such as 0.1 can be represented exactly in the decimal representation. floatdouble 標記法中,這類數位通常是無限的分數,因此這些標記法更容易發生舍入錯誤。In the float and double representations, such numbers are often infinite fractions, making those representations more prone to round-off errors.

如果二元運算子的其中一個運算元屬於 decimal類型,則另一個運算元必須是整數類型或類型 decimalIf one of the operands of a binary operator is of type decimal, then the other operand must be of an integral type or of type decimal. 如果整數類型運算元存在,則會先將它轉換成 decimal,然後才執行作業。If an integral type operand is present, it is converted to decimal before the operation is performed.

decimal 類型值上的運算結果是,這會因計算確切的結果(根據每個運算子定義的保留尺規)而產生,然後四捨五入以符合標記法。The result of an operation on values of type decimal is that which would result from calculating an exact result (preserving scale, as defined for each operator) and then rounding to fit the representation. 結果會舍入到最接近的可顯示值,而且當結果同樣接近兩個可顯示的值時,就是在最小有效位數位置(也就是「四進位」)中具有偶數數值的值。Results are rounded to the nearest representable value, and, when a result is equally close to two representable values, to the value that has an even number in the least significant digit position (this is known as "banker's rounding"). 零的結果一律具有0的正負號,而小數值為0。A zero result always has a sign of 0 and a scale of 0.

如果十進位算數運算產生的值小於或等於 5 * 10^-29 以絕對值表示,則作業的結果會變成零。If a decimal arithmetic operation produces a value less than or equal to 5 * 10^-29 in absolute value, the result of the operation becomes zero. 如果 decimal 算數運算產生的結果對 decimal 格式而言太大,則會擲回 System.OverflowExceptionIf a decimal arithmetic operation produces a result that is too large for the decimal format, a System.OverflowException is thrown.

decimal 類型的精確度較高,但範圍比浮點類型更小。The decimal type has greater precision but smaller range than the floating-point types. 因此,從浮點類型到 decimal 的轉換可能會產生溢位例外狀況,而從 decimal 到浮點類型的轉換可能會導致失去精確度。Thus, conversions from the floating-point types to decimal might produce overflow exceptions, and conversions from decimal to the floating-point types might cause loss of precision. 基於這些理由,浮點類型與 decimal之間不存在隱含轉換,而且沒有明確轉換,也無法在同一個運算式中混合使用浮點和 decimal 運算元。For these reasons, no implicit conversions exist between the floating-point types and decimal, and without explicit casts, it is not possible to mix floating-point and decimal operands in the same expression.

Bool 類型The bool type

bool 類型代表布林邏輯數量。The bool type represents boolean logical quantities. bool 類型的可能值為 truefalseThe possible values of type bool are true and false.

bool 和其他類型之間不存在標準轉換。No standard conversions exist between bool and other types. 特別是,bool 類型是不同的,而且與整數類資料類型不同,而且不能使用 bool 值來取代整數值,反之亦然。In particular, the bool type is distinct and separate from the integral types, and a bool value cannot be used in place of an integral value, and vice versa.

在 C 和C++語言中,零整數或浮點數,或 null 指標可以轉換成布林值 false和非零整數或浮點數,或非 null 指標可以轉換成布林值 true)。In the C and C++ languages, a zero integral or floating-point value, or a null pointer can be converted to the boolean value false, and a non-zero integral or floating-point value, or a non-null pointer can be converted to the boolean value true. 在C#中,這類轉換會藉由明確地將整數或浮點數與零進行比較,或明確地比較物件參考與 null來完成。In C#, such conversions are accomplished by explicitly comparing an integral or floating-point value to zero, or by explicitly comparing an object reference to null.

列舉類型Enumeration types

列舉類型是具有已命名常數的相異類型。An enumeration type is a distinct type with named constants. 每個列舉類型都具有基礎類型,必須是 bytesbyteshortushortintuintlongulongEvery enumeration type has an underlying type, which must be byte, sbyte, short, ushort, int, uint, long or ulong. 列舉類型的值集合與基礎類型的一組值相同。The set of values of the enumeration type is the same as the set of values of the underlying type. 列舉類型的值不限於已命名常數的值。Values of the enumeration type are not restricted to the values of the named constants. 列舉類型是透過列舉宣告(列舉宣告)來定義。Enumeration types are defined through enumeration declarations (Enum declarations).

可為 Null 的型別Nullable types

可為 null 的型別可以代表其基礎類型的所有值加上額外的 null 值。A nullable type can represent all values of its underlying type plus an additional null value. 可為 null 的型別會 T?寫入,其中 T 是基礎型別。A nullable type is written T?, where T is the underlying type. 此語法是 System.Nullable<T>的縮寫,而這兩種形式可以交換使用。This syntax is shorthand for System.Nullable<T>, and the two forms can be used interchangeably.

相反地,不可為 null 的實值型別就是除了 System.Nullable<T> 和其速記 T? (適用于任何 T)以外的任何實值型別,加上任何限制為不可為 null 的實值型別的型別參數(也就是具有 struct 的任何型別參數條件約束)。A non-nullable value type conversely is any value type other than System.Nullable<T> and its shorthand T? (for any T), plus any type parameter that is constrained to be a non-nullable value type (that is, any type parameter with a struct constraint). System.Nullable<T> 型別會指定 T型別參數條件約束)的實值型別條件約束,這表示可為 null 型別的基礎型別可以是任何不可為 null 的實值型別。The System.Nullable<T> type specifies the value type constraint for T (Type parameter constraints), which means that the underlying type of a nullable type can be any non-nullable value type. 可為 null 類型的基礎類型不能是可為 null 的類型或參考型別。The underlying type of a nullable type cannot be a nullable type or a reference type. 例如,int??string? 是不正確類型。For example, int?? and string? are invalid types.

可為 null 的型別 T? 的實例有兩個公用唯讀屬性:An instance of a nullable type T? has two public read-only properties:

  • 類型的 HasValue 屬性 boolA HasValue property of type bool
  • 類型的 Value 屬性 TA Value property of type T

HasValue 為 true 的實例稱為非 null。An instance for which HasValue is true is said to be non-null. 非 null 實例包含已知的值,Value 會傳回該值。A non-null instance contains a known value and Value returns that value.

HasValue 為 false 的實例稱為 null。An instance for which HasValue is false is said to be null. Null 實例有未定義的值。A null instance has an undefined value. 嘗試讀取 null 實例的 Value 會導致擲回 System.InvalidOperationExceptionAttempting to read the Value of a null instance causes a System.InvalidOperationException to be thrown. 存取可為 null 之實例之 Value 屬性的程式稱為解除包裝The process of accessing the Value property of a nullable instance is referred to as unwrapping.

除了預設的函式,每個可為 null 的型別 T? 都具有公用的函式,該函式會接受 T類型的單一引數。In addition to the default constructor, every nullable type T? has a public constructor that takes a single argument of type T. 假設 T類型的值 x,則為格式的函式呼叫Given a value x of type T, a constructor invocation of the form

new T?(x)

建立 T? 的非 null 實例,其 Value 屬性會 xcreates a non-null instance of T? for which the Value property is x. 針對指定的值建立可為 null 之型別的非 null 實例的程式稱為「包裝」。The process of creating a non-null instance of a nullable type for a given value is referred to as wrapping.

隱含轉換可從 null 常值取得,以 T?Null 常值轉換),以及從 TT?隱含可為 null 的轉換)。Implicit conversions are available from the null literal to T? (Null literal conversions) and from T to T? (Implicit nullable conversions).

參考型別Reference types

參考型別是類別類型、介面類別型、陣列類型或委派類型。A reference type is a class type, an interface type, an array type, or a delegate type.

reference_type
    : class_type
    | interface_type
    | array_type
    | delegate_type
    ;

class_type
    : type_name
    | 'object'
    | 'dynamic'
    | 'string'
    ;

interface_type
    : type_name
    ;

array_type
    : non_array_type rank_specifier+
    ;

non_array_type
    : type
    ;

rank_specifier
    : '[' dim_separator* ']'
    ;

dim_separator
    : ','
    ;

delegate_type
    : type_name
    ;

參考型別值是類型實例的參考,後者稱為物件A reference type value is a reference to an instance of the type, the latter known as an object. null 的特殊值與所有參考型別相容,並指出不存在實例。The special value null is compatible with all reference types and indicates the absence of an instance.

類別型別Class types

類別類型會定義資料結構,其中包含資料成員(常數和欄位)、函式成員(方法、屬性、事件、索引子、運算子、實例的函式、析構函式和靜態的函式)和巢狀型別。A class type defines a data structure that contains data members (constants and fields), function members (methods, properties, events, indexers, operators, instance constructors, destructors and static constructors), and nested types. 類別類型支援繼承,這是衍生類別可以擴充和特殊化基類的機制。Class types support inheritance, a mechanism whereby derived classes can extend and specialize base classes. 類別類型的實例是使用object_creation_expressions (物件建立運算式)所建立。Instances of class types are created using object_creation_expressions (Object creation expressions).

類別中會描述類別類型。Class types are described in Classes.

某些預先定義的C#類別類型在語言中具有特殊意義,如下表所述。Certain predefined class types have special meaning in the C# language, as described in the table below.

類別類型Class type 說明Description
System.Object 所有其他類型的最終基底類別。The ultimate base class of all other types. 請參閱物件類型See The object type.
System.String C#語言的字串類型。The string type of the C# language. 請參閱字串類型See The string type.
System.ValueType 所有實數值型別的基類。The base class of all value types. 請參閱system.object 類型See The System.ValueType type.
System.Enum 所有列舉類型的基類。The base class of all enum types. 參閱列舉。See Enums.
System.Array 所有陣列類型的基類。The base class of all array types. 請參閱陣列See Arrays.
System.Delegate 所有委派類型的基類。The base class of all delegate types. 請參閱委派See Delegates.
System.Exception 所有例外狀況類型的基類。The base class of all exception types. 請參閱例外狀況。See Exceptions.

物件型別The object type

object 類別類型是所有其他類型的最終基底類別。The object class type is the ultimate base class of all other types. 中C#的每個型別都是直接或間接衍生自 object 類別型別。Every type in C# directly or indirectly derives from the object class type.

關鍵字 object 只是預先定義之類別 System.Object的別名。The keyword object is simply an alias for the predefined class System.Object.

動態型別The dynamic type

dynamic 型別(例如 object)可以參考任何物件。The dynamic type, like object, can reference any object. 當運算子套用至 dynamic類型的運算式時,其解析會延遲到程式執行為止。When operators are applied to expressions of type dynamic, their resolution is deferred until the program is run. 因此,如果運算子無法合法套用至參考的物件,則在編譯期間不會提供任何錯誤。Thus, if the operator cannot legally be applied to the referenced object, no error is given during compilation. 相反地,當運算子的解析在執行時間失敗時,將會擲回例外狀況。Instead an exception will be thrown when resolution of the operator fails at run-time.

其目的是要允許動態系結,這在動態系結中有詳細的說明。Its purpose is to allow dynamic binding, which is described in detail in Dynamic binding.

dynamic 會視為與 object 相同,但下列方面除外:dynamic is considered identical to object except in the following respects:

  • dynamic 類型之運算式上的作業可以動態繫結(動態系結)。Operations on expressions of type dynamic can be dynamically bound (Dynamic binding).
  • 型別推斷(型別推斷)會偏好 objectdynamic,如果兩者都是候選項目。Type inference (Type inference) will prefer dynamic over object if both are candidates.

由於這項等價,下列內容包含:Because of this equivalence, the following holds:

  • objectdynamic之間,以及以 object 取代 dynamic 時,兩者之間有隱含的身分識別轉換。There is an implicit identity conversion between object and dynamic, and between constructed types that are the same when replacing dynamic with object
  • object 的隱含和明確轉換也適用于 dynamic的和。Implicit and explicit conversions to and from object also apply to and from dynamic.
  • object 取代 dynamic 時,方法簽章會被視為相同的簽章Method signatures that are the same when replacing dynamic with object are considered the same signature
  • 類型 dynamic 在執行時間與 object 不區分。The type dynamic is indistinguishable from object at run-time.
  • dynamic 類型的運算式稱為動態運算式An expression of the type dynamic is referred to as a dynamic expression.

字串型別The string type

string 類型是直接繼承自 object的密封類別類型。The string type is a sealed class type that inherits directly from object. string 類別的實例代表 Unicode 字元字串。Instances of the string class represent Unicode character strings.

string 類型的值可以撰寫為字串常值(字串常值)。Values of the string type can be written as string literals (String literals).

關鍵字 string 只是預先定義之類別 System.String的別名。The keyword string is simply an alias for the predefined class System.String.

介面型別Interface types

介面會定義合約。An interface defines a contract. 實作為介面的類別或結構必須遵守其合約。A class or struct that implements an interface must adhere to its contract. 介面可能繼承自多個基底介面,而類別或結構可能會執行多個介面。An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.

介面類別型會在介面中說明。Interface types are described in Interfaces.

陣列型別Array types

陣列是一種資料結構,其中包含零個或多個透過計算索引存取的變數。An array is a data structure that contains zero or more variables which are accessed through computed indices. 陣列中包含的變數(也稱為陣列的元素)都是相同的類型,而此類型稱為陣列的元素類型。The variables contained in an array, also called the elements of the array, are all of the same type, and this type is called the element type of the array.

陣列中會描述陣列類型。Array types are described in Arrays.

委派型別Delegate types

「委派」(delegate)是指一或多個方法的資料結構。A delegate is a data structure that refers to one or more methods. 若為實例方法,它也會參考其對應的物件實例。For instance methods, it also refers to their corresponding object instances.

C 或C++中委派最接近的對等是函式指標,但函式指標只能參考靜態函式,而委派可以同時參考靜態和實例方法。The closest equivalent of a delegate in C or C++ is a function pointer, but whereas a function pointer can only reference static functions, a delegate can reference both static and instance methods. 在後者的情況下,委派不僅會儲存對方法進入點的參考,也會存放要叫用方法之物件實例的參考。In the latter case, the delegate stores not only a reference to the method's entry point, but also a reference to the object instance on which to invoke the method.

委派中會描述委派類型。Delegate types are described in Delegates.

Boxing 和 UnboxingBoxing and unboxing

裝箱和取消裝箱的概念是類型系統C#的核心。The concept of boxing and unboxing is central to C#'s type system. 它會允許value_type的任何值在類型 object之間來回轉換,藉此提供value_types 與reference_type之間的橋樑。It provides a bridge between value_types and reference_types by permitting any value of a value_type to be converted to and from type object. 「裝箱」和「取消裝箱」可讓類型系統的統一視圖,其中任何類型的值最終可以視為物件。Boxing and unboxing enables a unified view of the type system wherein a value of any type can ultimately be treated as an object.

裝箱轉換Boxing conversions

「裝箱」轉換允許將value_type隱含地轉換成reference_typeA boxing conversion permits a value_type to be implicitly converted to a reference_type. 有下列的裝箱轉換:The following boxing conversions exist:

  • 從任何value_type到類型 objectFrom any value_type to the type object.
  • 從任何value_type到類型 System.ValueTypeFrom any value_type to the type System.ValueType.
  • 從任何non_nullable_value_typevalue_type所執行的任何interface_typeFrom any non_nullable_value_type to any interface_type implemented by the value_type.
  • 從任何nullable_typenullable_type基礎類型所實interface_type的任何。From any nullable_type to any interface_type implemented by the underlying type of the nullable_type.
  • 從任何enum_type到類型 System.EnumFrom any enum_type to the type System.Enum.
  • 從任何具有基礎enum_typenullable_type到類型 System.EnumFrom any nullable_type with an underlying enum_type to the type System.Enum.
  • 請注意,從型別參數隱含的轉換會當做「裝箱」轉換來執行(如果在執行時間,它最後會從實值型別轉換成引用型別(包括型別參數的隱含轉換)。Note that an implicit conversion from a type parameter will be executed as a boxing conversion if at run-time it ends up converting from a value type to a reference type (Implicit conversions involving type parameters).

non_nullable_value_type的值進行裝箱,包括設定物件實例,以及將non_nullable_value_type值複製到該實例。Boxing a value of a non_nullable_value_type consists of allocating an object instance and copying the non_nullable_value_type value into that instance.

如果nullable_type的值為 null 值(HasValue false),或解除包裝並將基礎值裝箱的結果,則會產生 null 參考。Boxing a value of a nullable_type produces a null reference if it is the null value (HasValue is false), or the result of unwrapping and boxing the underlying value otherwise.

若要將non_nullable_value_type的值進行裝箱,最佳的處理方式是想像泛型的裝箱類別是否存在,其行為就如同宣告如下:The actual process of boxing a value of a non_nullable_value_type is best explained by imagining the existence of a generic boxing class, which behaves as if it were declared as follows:

sealed class Box<T>: System.ValueType
{
    T value;

    public Box(T t) {
        value = t;
    }
}

T 類型的值 v 的裝箱現在包含執行運算式 new Box<T>(v),並以 object類型的值傳回產生的實例。Boxing of a value v of type T now consists of executing the expression new Box<T>(v), and returning the resulting instance as a value of type object. 因此,語句Thus, the statements

int i = 123;
object box = i;

概念上對應至conceptually correspond to

int i = 123;
object box = new Box<int>(i);

如上 Box<T> 的裝箱類別並不存在,而且已裝箱值的動態類型實際上不是類別類型。A boxing class like Box<T> above doesn't actually exist and the dynamic type of a boxed value isn't actually a class type. 相反地,T 類型的已裝箱值具有動態類型 T,而使用 is 運算子的動態類型檢查可以直接參考類型 TInstead, a boxed value of type T has the dynamic type T, and a dynamic type check using the is operator can simply reference type T. 例如,套用至物件的For example,

int i = 123;
object box = i;
if (box is int) {
    Console.Write("Box contains an int");
}

會在主控台上輸出字串 "Box contains an int"。will output the string "Box contains an int" on the console.

「裝箱」轉換意指建立所要封裝之值的複本。A boxing conversion implies making a copy of the value being boxed. 這不同于reference_type轉換成類型 object,其中值會繼續參考相同的實例,而且只會被視為較少的衍生類型 objectThis is different from a conversion of a reference_type to type object, in which the value continues to reference the same instance and simply is regarded as the less derived type object. 例如,假設宣告For example, given the declaration

struct Point
{
    public int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

下列語句the following statements

Point p = new Point(10, 10);
object box = p;
p.x = 20;
Console.Write(((Point)box).x);

會在主控台上輸出值10,因為 box 指派 p 中的隱含裝箱作業會導致複製 p 的值。will output the value 10 on the console because the implicit boxing operation that occurs in the assignment of p to box causes the value of p to be copied. 已將 Point 宣告為 class,則值20會是輸出,因為 pbox 會參考相同的實例。Had Point been declared a class instead, the value 20 would be output because p and box would reference the same instance.

取消裝箱轉換Unboxing conversions

「取消裝箱」轉換允許將reference_type明確轉換成value_typeAn unboxing conversion permits a reference_type to be explicitly converted to a value_type. 下列的取消裝箱轉換已存在:The following unboxing conversions exist:

  • 從 [類型] object 到任何value_typeFrom the type object to any value_type.
  • 從 [類型] System.ValueType 到任何value_typeFrom the type System.ValueType to any value_type.
  • 從任何interface_type到任何會執行interface_typenon_nullable_value_typeFrom any interface_type to any non_nullable_value_type that implements the interface_type.
  • 從任何interface_type到其基礎類型會實作為interface_type的任何nullable_typeFrom any interface_type to any nullable_type whose underlying type implements the interface_type.
  • 從 [類型] System.Enum 到任何enum_typeFrom the type System.Enum to any enum_type.
  • 從類型 System.Enum 至具有基礎enum_type的任何nullable_typeFrom the type System.Enum to any nullable_type with an underlying enum_type.
  • 請注意,明確轉換為類型參數時,如果是在執行時間將其從參考型別轉換成實值型別(明確動態轉換),就會以「取消鎖定」轉換的方式執行。Note that an explicit conversion to a type parameter will be executed as an unboxing conversion if at run-time it ends up converting from a reference type to a value type (Explicit dynamic conversions).

Non_nullable_value_type的取消裝箱作業包含第一次檢查物件實例是否為給定non_nullable_value_type的已裝箱值,然後將值從實例中複製出來。An unboxing operation to a non_nullable_value_type consists of first checking that the object instance is a boxed value of the given non_nullable_value_type, and then copying the value out of the instance.

如果 null來源運算元,則取消裝箱至nullable_type會產生nullable_type的 null 值,否則會將物件實例取消包裝到nullable_type的基礎類型。Unboxing to a nullable_type produces the null value of the nullable_type if the source operand is null, or the wrapped result of unboxing the object instance to the underlying type of the nullable_type otherwise.

參考上一節所述的虛數裝箱類別,將物件 box 的取消裝箱轉換為value_type T 由執行運算式 ((Box<T>)box).value所組成。Referring to the imaginary boxing class described in the previous section, an unboxing conversion of an object box to a value_type T consists of executing the expression ((Box<T>)box).value. 因此,語句Thus, the statements

object box = 123;
int i = (int)box;

概念上對應至conceptually correspond to

object box = new Box<int>(123);
int i = ((Box<int>)box).value;

對於給定non_nullable_value_type在執行時間成功的取消裝箱轉換,來源運算元的值必須是該non_nullable_value_type之已裝箱值的參考。For an unboxing conversion to a given non_nullable_value_type to succeed at run-time, the value of the source operand must be a reference to a boxed value of that non_nullable_value_type. 如果 null來源運算元,則會擲回 System.NullReferenceExceptionIf the source operand is null, a System.NullReferenceException is thrown. 如果來源運算元是不相容物件的參考,則會擲回 System.InvalidCastExceptionIf the source operand is a reference to an incompatible object, a System.InvalidCastException is thrown.

對於給定nullable_type在執行時間成功的取消裝箱轉換,來源運算元的值必須是 nullnullable_type之基礎non_nullable_value_type的已裝箱值的參考。For an unboxing conversion to a given nullable_type to succeed at run-time, the value of the source operand must be either null or a reference to a boxed value of the underlying non_nullable_value_type of the nullable_type. 如果來源運算元是不相容物件的參考,則會擲回 System.InvalidCastExceptionIf the source operand is a reference to an incompatible object, a System.InvalidCastException is thrown.

結構化類型Constructed types

泛型型別宣告本身則代表一個未系結的泛型型別,它是用來做為「藍圖」,藉由套用型別引數來形成許多不同的類型。A generic type declaration, by itself, denotes an unbound generic type that is used as a "blueprint" to form many different types, by way of applying type arguments. 型別引數是以在泛型型別名稱之後的角括弧(<>)撰寫。The type arguments are written within angle brackets (< and >) immediately following the name of the generic type. 包含至少一個型別引數的型別稱為「結構化型別」。A type that includes at least one type argument is called a constructed type. 在可顯示類型名稱的語言中,大部分的位置都可以使用結構化類型。A constructed type can be used in most places in the language in which a type name can appear. 未系結的泛型型別只能用在typeof_expressiontypeof 運算子)內。An unbound generic type can only be used within a typeof_expression (The typeof operator).

結構化類型也可以在運算式中當做簡單名稱(簡單名稱),或在存取成員(成員存取)時使用。Constructed types can also be used in expressions as simple names (Simple names) or when accessing a member (Member access).

評估namespace_or_type_name時,只會考慮具有正確數目之類型參數的泛型型別。When a namespace_or_type_name is evaluated, only generic types with the correct number of type parameters are considered. 因此,只要類型的類型參數數目不同,就可以使用相同的識別碼來識別不同的類型。Thus, it is possible to use the same identifier to identify different types, as long as the types have different numbers of type parameters. 在相同的程式中混合泛型和非泛型類別時,這會很有用:This is useful when mixing generic and non-generic classes in the same program:

namespace Widgets
{
    class Queue {...}
    class Queue<TElement> {...}
}

namespace MyApplication
{
    using Widgets;

    class X
    {
        Queue q1;            // Non-generic Widgets.Queue
        Queue<int> q2;       // Generic Widgets.Queue
    }
}

Type_name可能會識別已建立的類型,即使它並未直接指定類型參數也一樣。A type_name might identify a constructed type even though it doesn't specify type parameters directly. 這種情況可能發生在泛型類別宣告內的類型,而且包含宣告的實例類型會隱含用於名稱查閱(泛型類別中的巢狀型別):This can occur where a type is nested within a generic class declaration, and the instance type of the containing declaration is implicitly used for name lookup (Nested types in generic classes):

class Outer<T>
{
    public class Inner {...}

    public Inner i;                // Type of i is Outer<T>.Inner
}

在 unsafe 程式碼中,不能使用結構化類型做為unmanaged_type指標類型)。In unsafe code, a constructed type cannot be used as an unmanaged_type (Pointer types).

型別引數Type arguments

型別引數清單中的每個引數都只是一個別。Each argument in a type argument list is simply a type.

type_argument_list
    : '<' type_arguments '>'
    ;

type_arguments
    : type_argument (',' type_argument)*
    ;

type_argument
    : type
    ;

在 unsafe 程式碼(unsafe 程式碼)中, type_argument可能不是指標類型。In unsafe code (Unsafe code), a type_argument may not be a pointer type. 每個型別引數都必須滿足對應型別參數的任何條件約束(型別參數條件約束)。Each type argument must satisfy any constraints on the corresponding type parameter (Type parameter constraints).

開啟和關閉類型Open and closed types

所有類型都可以分類為開放式類型封閉式類型All types can be classified as either open types or closed types. 「開啟類型」是包含型別參數的型別。An open type is a type that involves type parameters. 更具體而言:More specifically:

  • 型別參數會定義開放式型別。A type parameter defines an open type.
  • 只有在其專案類型為開放式類型時,陣列類型才是開啟類型。An array type is an open type if and only if its element type is an open type.
  • 如果只有一或多個型別引數是開放式型別,則結構化型別就是開放式型別。A constructed type is an open type if and only if one or more of its type arguments is an open type. 只有當一個或多個類型引數或其包含類型的類型引數是開放式類型時,結構化的巢狀型別才是開放式類型。A constructed nested type is an open type if and only if one or more of its type arguments or the type arguments of its containing type(s) is an open type.

封閉式類型是不是開放式類型的類型。A closed type is a type that is not an open type.

在執行時間,泛型型別宣告內的所有程式碼都是在封閉式結構型別的內容中執行,而這是透過將型別引數套用至泛型宣告所建立。At run-time, all of the code within a generic type declaration is executed in the context of a closed constructed type that was created by applying type arguments to the generic declaration. 泛型型別中的每個型別參數都會系結至特定的執行時間型別。Each type parameter within the generic type is bound to a particular run-time type. 所有語句和運算式的執行時間處理一律會發生于封閉式類型,而開放式類型只會在編譯時間處理期間發生。The run-time processing of all statements and expressions always occurs with closed types, and open types occur only during compile-time processing.

每個封閉的結構類型都有自己的靜態變數集,不會與任何其他已關閉的結構類型共用。Each closed constructed type has its own set of static variables, which are not shared with any other closed constructed types. 由於開啟的類型不存在於執行時間,因此沒有與開放式類型相關聯的靜態變數。Since an open type does not exist at run-time, there are no static variables associated with an open type. 如果兩個封閉的結構型別是從相同的未系結泛型型別進行構造,而且其對應的型別引數都是相同的型別,Two closed constructed types are the same type if they are constructed from the same unbound generic type, and their corresponding type arguments are the same type.

系結和未系結類型Bound and unbound types

「未系結類型」一詞指的是非泛型型別或未系結的泛型型別。The term unbound type refers to a non-generic type or an unbound generic type. 「系結別」一詞指的是非泛型型別或結構化型別。The term bound type refers to a non-generic type or a constructed type.

未系結的型別是指由型別宣告所宣告的實體。An unbound type refers to the entity declared by a type declaration. 未系結的泛型型別本身不是類型,而且不能當做變數、引數或傳回值的類型或基底類型使用。An unbound generic type is not itself a type, and cannot be used as the type of a variable, argument or return value, or as a base type. 唯一可以參考未系結泛型型別的結構是 typeof 運算式(typeof 運算子)。The only construct in which an unbound generic type can be referenced is the typeof expression (The typeof operator).

滿足條件約束Satisfying constraints

每當參考了結構化型別或泛型方法時,就會針對泛型型別或方法(型別參數條件約束)上宣告的型別參數條件約束,檢查提供的型別引數。Whenever a constructed type or generic method is referenced, the supplied type arguments are checked against the type parameter constraints declared on the generic type or method (Type parameter constraints). 針對每個 where 子句,會針對每個條件約束檢查對應至命名類型參數的類型引數 A,如下所示:For each where clause, the type argument A that corresponds to the named type parameter is checked against each constraint as follows:

  • 如果條件約束是類別類型、介面類別型或類型參數,則 let C 會以提供的類型引數取代條件約束中出現的任何類型參數,來表示該條件約束。If the constraint is a class type, an interface type, or a type parameter, let C represent that constraint with the supplied type arguments substituted for any type parameters that appear in the constraint. 若要滿足條件約束,必須將類型 A 轉換成下列其中一項所 C 的類型:To satisfy the constraint, it must be the case that type A is convertible to type C by one of the following:
  • 如果條件約束是參考型別條件約束(class),則類型 A 必須符合下列其中一項:If the constraint is the reference type constraint (class), the type A must satisfy one of the following:
    • A 是介面型別、類別型別、委派型別或陣列型別。A is an interface type, class type, delegate type or array type. 請注意,System.ValueTypeSystem.Enum 是符合此條件約束的參考型別。Note that System.ValueType and System.Enum are reference types that satisfy this constraint.
    • A 是已知為參考型別的型別參數(型別參數條件約束)。A is a type parameter that is known to be a reference type (Type parameter constraints).
  • 如果條件約束是實值型別條件約束(struct),則型別 A 必須滿足下列其中一項:If the constraint is the value type constraint (struct), the type A must satisfy one of the following:
    • A 是結構型別或列舉型別,但不能是可為 null 的型別。A is a struct type or enum type, but not a nullable type. 請注意,System.ValueTypeSystem.Enum 是不符合此條件約束的參考型別。Note that System.ValueType and System.Enum are reference types that do not satisfy this constraint.
    • A 是具有實數值型別條件約束的類型參數(類型參數條件約束)。A is a type parameter having the value type constraint (Type parameter constraints).
  • 如果條件約束是 new()的函式條件約束,則類型 A 不得 abstract,而且必須具有公用無參數的函式。If the constraint is the constructor constraint new(), the type A must not be abstract and must have a public parameterless constructor. 如果下列其中一項為真,就會滿足此情況:This is satisfied if one of the following is true:
    • A 是實數值型別,因為所有實數值型別都具有公用預設的函式(預設的函式)。A is a value type, since all value types have a public default constructor (Default constructors).
    • A 是具有「函式條件約束」(型別參數條件約束)的型別參數。A is a type parameter having the constructor constraint (Type parameter constraints).
    • A 是具有實數值型別條件約束的類型參數(類型參數條件約束)。A is a type parameter having the value type constraint (Type parameter constraints).
    • A 是不 abstract 的類別,而且包含明確宣告的 public 不含任何參數的函式。A is a class that is not abstract and contains an explicitly declared public constructor with no parameters.
    • Aabstract,而且具有預設的函式(預設的函式)。A is not abstract and has a default constructor (Default constructors).

如果指定的型別引數不符合一個或多個型別參數的條件約束,就會發生編譯時期錯誤。A compile-time error occurs if one or more of a type parameter's constraints are not satisfied by the given type arguments.

因為類型參數不會繼承,所以永遠不會繼承條件約束。Since type parameters are not inherited, constraints are never inherited either. 在下列範例中,D 需要在其型別參數上指定條件約束 T,讓 T 滿足基類 B<T>所強加的條件約束。In the example below, D needs to specify the constraint on its type parameter T so that T satisfies the constraint imposed by the base class B<T>. 相反地,類別 E 不需要指定條件約束,因為 List<T> 會針對任何 T來執行 IEnumerableIn contrast, class E need not specify a constraint, because List<T> implements IEnumerable for any T.

class B<T> where T: IEnumerable {...}

class D<T>: B<T> where T: IEnumerable {...}

class E<T>: B<List<T>> {...}

型別參數Type parameters

型別參數是一個識別碼,用來指定在執行時間系結參數的實值型別或參考型別。A type parameter is an identifier designating a value type or reference type that the parameter is bound to at run-time.

type_parameter
    : identifier
    ;

因為類型參數可以使用許多不同的實際類型引數具現化,所以類型參數與其他類型的作業和限制會稍有不同。Since a type parameter can be instantiated with many different actual type arguments, type parameters have slightly different operations and restrictions than other types. 它們包括:These include:

就型別而言,型別參數純粹是編譯時間結構。As a type, type parameters are purely a compile-time construct. 在執行時間,每個型別參數都會系結至執行時間型別,其指定方式是提供泛型型別宣告的型別引數。At run-time, each type parameter is bound to a run-time type that was specified by supplying a type argument to the generic type declaration. 因此,使用型別參數宣告之變數的型別將會在執行時間為封閉的結構化型別(開放式和封閉式類型)。Thus, the type of a variable declared with a type parameter will, at run-time, be a closed constructed type (Open and closed types). 所有涉及型別參數之語句和運算式的執行時間執行,都會使用當做該參數的型別引數提供的實際型別。The run-time execution of all statements and expressions involving type parameters uses the actual type that was supplied as the type argument for that parameter.

運算式樹狀架構類型Expression tree types

運算式樹狀架構允許將 lambda 運算式表示為資料結構,而不是可執行檔程式碼。Expression trees permit lambda expressions to be represented as data structures instead of executable code. 運算式樹狀架構是 System.Linq.Expressions.Expression<D>形式之運算式樹狀架構類型的值,其中 D 是任何委派類型。Expression trees are values of expression tree types of the form System.Linq.Expressions.Expression<D>, where D is any delegate type. 針對此規格的其餘部分,我們將使用速記 Expression<D>來參考這些類型。For the remainder of this specification we will refer to these types using the shorthand Expression<D>.

如果從 lambda 運算式到委派類型 D的轉換存在,Expression<D>的運算式樹狀架構類型也會有轉換。If a conversion exists from a lambda expression to a delegate type D, a conversion also exists to the expression tree type Expression<D>. 當 lambda 運算式轉換成委派類型時,會產生一個委派來參考 lambda 運算式的可執行程式碼,而轉換成運算式樹狀架構類型會建立 lambda 運算式的運算式樹狀結構標記法。Whereas the conversion of a lambda expression to a delegate type generates a delegate that references executable code for the lambda expression, conversion to an expression tree type creates an expression tree representation of the lambda expression.

運算式樹狀架構是 lambda 運算式的有效率記憶體內部資料標記法,並可讓 lambda 運算式的結構變成透明和明確。Expression trees are efficient in-memory data representations of lambda expressions and make the structure of the lambda expression transparent and explicit.

就像委派型別 DExpression<D> 會有參數和傳回型別,這與 D的類型相同。Just like a delegate type D, Expression<D> is said to have parameter and return types, which are the same as those of D.

下列範例會將 lambda 運算式表示為可執行程式碼和運算式樹狀架構。The following example represents a lambda expression both as executable code and as an expression tree. 因為 Func<int,int>的轉換存在,Expression<Func<int,int>>的轉換也存在:Because a conversion exists to Func<int,int>, a conversion also exists to Expression<Func<int,int>>:

Func<int,int> del = x => x + 1;                    // Code

Expression<Func<int,int>> exp = x => x + 1;        // Data

在這些指派之後,委派 del 會參考傳回 x + 1的方法,而且運算式樹狀架構 exp 會參考描述運算式 x => x + 1的資料結構。Following these assignments, the delegate del references a method that returns x + 1, and the expression tree exp references a data structure that describes the expression x => x + 1.

泛型型別的確切定義 Expression<D> 以及將 lambda 運算式轉換成運算式樹狀架構類型時,用來建立運算式樹狀架構的精確規則,兩者都在此規格的範圍之外。The exact definition of the generic type Expression<D> as well as the precise rules for constructing an expression tree when a lambda expression is converted to an expression tree type, are both outside the scope of this specification.

明確來說,有兩件事要特別注意:Two things are important to make explicit:

  • 並非所有 lambda 運算式都可以轉換成運算式樹狀架構。Not all lambda expressions can be converted to expression trees. 例如,具有語句主體的 lambda 運算式,以及包含指派運算式的 lambda 運算式無法表示。For instance, lambda expressions with statement bodies, and lambda expressions containing assignment expressions cannot be represented. 在這些情況下,轉換仍然存在,但會在編譯時間失敗。In these cases, a conversion still exists, but will fail at compile-time. 這些例外狀況詳述于匿名函數轉換中。These exceptions are detailed in Anonymous function conversions.

  • Expression<D> 提供實例方法 Compile,其會產生類型 D的委派:Expression<D> offers an instance method Compile which produces a delegate of type D:

    Func<int,int> del2 = exp.Compile();
    

    叫用此委派會使運算式樹狀架構所代表的程式碼執行。Invoking this delegate causes the code represented by the expression tree to be executed. 因此,在上述定義中,del 和 del2 是相同的,而下列兩個語句會有相同的效果:Thus, given the definitions above, del and del2 are equivalent, and the following two statements will have the same effect:

    int i1 = del(1);
    
    int i2 = del2(1);
    

    執行此程式碼之後,i1i2 都會有 2的值。After executing this code, i1 and i2 will both have the value 2.