TürlerTypes

C# dilinin türleri iki ana kategoriye ayrılmıştır: değer türleri _ ve _başvuru türleri*.The types of the C# language are divided into two main categories: value types _ and _reference types*. Hem değer türleri hem de başvuru türleri Genel türler olabilir ve bu, bir veya daha fazla _ tür parametresi * alır.Both value types and reference types may be generic types, which take one or more _*type parameters**. Tür parametreleri hem değer türlerini hem de başvuru türlerini belirleyebilir.Type parameters can designate both value types and reference types.

type
    : value_type
    | reference_type
    | type_parameter
    | type_unsafe
    ;

Türlerin son kategorisi, işaretçiler, yalnızca güvenli olmayan kodda kullanılabilir.The final category of types, pointers, is available only in unsafe code. Bu, işaretçi türlerindedaha fazla ele alınmıştır.This is discussed further in Pointer types.

Değer türleri, değer türlerinin değişkenlerinin verilerini doğrudan içerdiği başvuru türlerinden farklıdır, ancak başvuru türleri **deposu *, _ **nesneler * olarak bilinirler.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**. Başvuru türleriyle, iki değişken aynı nesneye başvurabilir ve bu nedenle bir değişkende işlemler, diğer değişken tarafından başvurulan nesneyi etkilemek için mümkündür.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. Değer türleriyle, her birinin kendi verilerinin bir kopyasına sahip olduğu ve bir üzerindeki işlemlerin diğerini etkilemesi mümkün değildir.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# tür sistemi, herhangi bir türden bir değer bir nesne olarak işlenemeyeceği şekilde birleştirilmiştir.C#'s type system is unified such that a value of any type can be treated as an object. C# içindeki her tür doğrudan veya dolaylı olarak object sınıf türünden türetilir ve object tüm türlerin en son temel sınıfıdır.Every type in C# directly or indirectly derives from the object class type, and object is the ultimate base class of all types. Başvuru türlerinin değerleri, yalnızca değerleri tür olarak görüntüleyerek nesne olarak değerlendirilir object .Values of reference types are treated as objects simply by viewing the values as type object. Değer türlerinin değerleri, kutulama ve kutudan çıkarma işlemleri (kutulama ve kutudançıkarma) gerçekleştirerek nesneler olarak değerlendirilir.Values of value types are treated as objects by performing boxing and unboxing operations (Boxing and unboxing).

Değer türleriValue types

Değer türü bir struct türü ya da bir numaralandırma türüdür.A value type is either a struct type or an enumeration type. C# basit türler adlı önceden tanımlanmış bir yapı türleri kümesi sağlar.C# provides a set of predefined struct types called the simple types. Basit türler, ayrılmış sözcükler aracılığıyla tanımlanır.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
    ;

Bir başvuru türü değişkeninin aksine, değer türü değişkeni null yalnızca değer türü null yapılabilir bir tür ise değeri içerebilir.Unlike 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. Her null yapılamayan değer türü için, aynı değer kümesini ve değeri belirten karşılık gelen null yapılabilir bir değer türü vardır null .For every non-nullable value type there is a corresponding nullable value type denoting the same set of values plus the value null.

Değer türünde bir değişkene atama, atanmakta olan değerin bir kopyasını oluşturur.Assignment to a variable of a value type creates a copy of the value being assigned. Bu, atamadan bir başvuru türü değişkenine farklılık gösterir ve başvuruyu, başvuru tarafından tanımlanan nesneyi kopyalar.This differs from assignment to a variable of a reference type, which copies the reference but not the object identified by the reference.

System. ValueType türüThe System.ValueType type

Tüm değer türleri dolaylı olarak sınıfından devralınır System.ValueType , bu, sırasıyla sınıfından devralır object .All value types implicitly inherit from the class System.ValueType, which, in turn, inherits from class object. Herhangi bir türün bir değer türünden türemesini mümkün değildir ve değer türleri örtülü olarak mühürlenebilir (korumalı sınıflardır).It is not possible for any type to derive from a value type, and value types are thus implicitly sealed (Sealed classes).

Bunun System.ValueType kendisi bir value_type değildir.Note that System.ValueType is not itself a value_type. Bunun yerine, tüm value_type öğeleri otomatik olarak türetildiği bir class_type .Rather, it is a class_type from which all value_type s are automatically derived.

Varsayılan oluşturucularDefault constructors

Tüm değer türleri örtük olarak *Varsayılan Oluşturucu _ adlı bir ortak parametresiz örnek Oluşturucusu bildirir.All value types implicitly declare a public parameterless instance constructor called the *default constructor _. Varsayılan Oluşturucu, değer türü için _ varsayılan değeri* olarak bilinen sıfır ile başlatılmış bir örnek döndürür:The default constructor returns a zero-initialized instance known as the _ default value* for the value type:

  • Tüm Simple_Type s için, varsayılan değer tüm sıfırlardan oluşan bir bit düzeniyle oluşturulan değerdir:For all simple_type s, the default value is the value produced by a bit pattern of all zeros:
    • ,,,,, sbyte byte short ushort int uint , long Ve için ulong varsayılan değer 0 .For sbyte, byte, short, ushort, int, uint, long, and ulong, the default value is 0.
    • İçin char varsayılan değer '\x0000' .For char, the default value is '\x0000'.
    • İçin float varsayılan değer 0.0f .For float, the default value is 0.0f.
    • İçin double varsayılan değer 0.0d .For double, the default value is 0.0d.
    • İçin decimal varsayılan değer 0.0m .For decimal, the default value is 0.0m.
    • İçin bool varsayılan değer false .For bool, the default value is false.
  • Enum_type için, E varsayılan değer 0 türüne dönüştürülür E .For an enum_type E, the default value is 0, converted to the type E.
  • Bir struct_type için varsayılan değer, tüm değer türü alanları varsayılan değerlerine ve tüm başvuru türü alanlarına ayarlanarak oluşturulan değerdir 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 için varsayılan değer, HasValue özelliğin yanlış olduğu ve özelliğin tanımsız olduğu bir örneğidir Value .For a nullable_type the default value is an instance for which the HasValue property is false and the Value property is undefined. Varsayılan değer null yapılabilir türün null değeri olarak da bilinir.The default value is also known as the null value of the nullable type.

Diğer örnek Oluşturucu gibi, bir değer türünün varsayılan Oluşturucusu işleci kullanılarak çağrılır new .Like any other instance constructor, the default constructor of a value type is invoked using the new operator. Verimlilik açısından, bu gereksinim aslında uygulamanın bir Oluşturucu çağrısı oluşturması için tasarlanmamıştır.For efficiency reasons, this requirement is not intended to actually have the implementation generate a constructor call. Aşağıdaki örnekte, değişkenleri i ve j her ikisi de sıfır olarak başlatılır.In the example below, variables i and j are both initialized to zero.

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

Her değer türünün örtük olarak ortak parametresiz bir örnek Oluşturucusu olduğundan, bir yapı türünün parametresiz bir oluşturucunun açık bir bildirimini içermesi mümkün değildir.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. Yapı türüne ancak parametreli örnek oluşturucuları (oluşturucular) bildirme izni verilir.A struct type is however permitted to declare parameterized instance constructors (Constructors).

Yapı türleriStruct types

Yapı türü, sabitler, alanlar, Yöntemler, özellikler, Dizin oluşturucular, işleçler, örnek oluşturucular, statik oluşturucular ve iç içe geçmiş türleri bildirebilen bir değer türüdür.A struct type is a value type that can declare constants, fields, methods, properties, indexers, operators, instance constructors, static constructors, and nested types. Struct türlerinin bildirimi struct bildirimlerindeaçıklanmıştır.The declaration of struct types is described in Struct declarations.

Basit türlerSimple types

C# basit türler adlı önceden tanımlanmış bir yapı türleri kümesi sağlar.C# provides a set of predefined struct types called the simple types. Basit türler ayrılmış sözcükler aracılığıyla tanımlanır, ancak bu ayrılmış sözcükler, System Aşağıdaki tabloda açıklandığı gibi, ad alanındaki önceden tanımlanmış yapı türleri için yalnızca diğer adlardır.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.

Ayrılmış sözcükReserved word Diğer ad türü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

Basit bir tür bir struct türü olarak diğer ad olduğundan, her basit türün üyeleri vardır.Because a simple type aliases a struct type, every simple type has members. Örneğin, int içinde belirtilen üyelere System.Int32 ve öğesinden devralınan üyelere sahiptir System.Object ve aşağıdaki deyimlere izin verilir: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

Basit türler, bazı ek işlemlere izin veren diğer yapı türlerinden farklıdır:The simple types differ from other struct types in that they permit certain additional operations:

  • Çoğu basit tür değerleri değişmez değerler (değişmezdeğerler) yazılarak oluşturulacak şekilde izin verir.Most simple types permit values to be created by writing literals (Literals). Örneğin, 123 türünde bir sabit değerdir int ve 'a' türünde bir sabit değerdir char .For example, 123 is a literal of type int and 'a' is a literal of type char. C#, genel olarak yapı türlerinin değişmez değerleri için bir provizyon yapmaz ve diğer yapı türlerinin varsayılan olmayan değerleri, sonuçta bu yapı türlerinin örnek oluşturucular aracılığıyla her zaman oluşturulur.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.
  • Bir ifadenin işlenenleri tüm basit tür sabitlersiyse, derleyicinin derlemeyi derleme zamanında değerlendirmesi mümkündür.When the operands of an expression are all simple type constants, it is possible for the compiler to evaluate the expression at compile-time. Böyle bir ifade constant_expression (sabit ifadeler) olarak bilinir.Such an expression is known as a constant_expression (Constant expressions). Diğer yapı türleri tarafından tanımlanan işleçleri içeren ifadeler sabit ifadeler olarak kabul edilmez.Expressions involving operators defined by other struct types are not considered to be constant expressions.
  • constBildirimler aracılığıyla basit türlerin (sabitler) sabitlerini bildirmek mümkündür.Through const declarations it is possible to declare constants of the simple types (Constants). Diğer yapı türlerinin sabitlerinin olması mümkün değildir ancak alanlar tarafından benzer bir efekt sağlanır static readonly .It is not possible to have constants of other struct types, but a similar effect is provided by static readonly fields.
  • Basit türler içeren dönüştürmeler, diğer yapı türleri tarafından tanımlanan dönüştürme işleçleri değerlendirmesinde yer alabilir, ancak kullanıcı tanımlı bir dönüştürme işleci hiçbir şekilde Kullanıcı tanımlı başka bir işlecin değerlendirilmesine (Kullanıcı tanımlı dönüştürmelerin değerlendirmesi) katılmaz.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 türleriIntegral types

C# dokuz integral türünü destekler: sbyte , byte , short , ushort , int , uint , long , ulong , ve char .C# supports nine integral types: sbyte, byte, short, ushort, int, uint, long, ulong, and char. İntegral türleri aşağıdaki boyutlara ve değer aralıklarına sahiptir:The integral types have the following sizes and ranges of values:

  • sbyteTür,-128 ve 127 arasındaki değerlerle işaretli 8 bit tamsayıları temsil eder.The sbyte type represents signed 8-bit integers with values between -128 and 127.
  • byteTür, 0 ile 255 arasında değerler içeren işaretsiz 8 bit tamsayılar temsil eder.The byte type represents unsigned 8-bit integers with values between 0 and 255.
  • shortTür,-32768 ve 32767 arasındaki değerlerle işaretli 16 bit tamsayılar temsil eder.The short type represents signed 16-bit integers with values between -32768 and 32767.
  • ushortTür, 0 ile 65535 arasındaki değerlere sahip işaretsiz 16 bit tamsayılar temsil eder.The ushort type represents unsigned 16-bit integers with values between 0 and 65535.
  • intTür,-2147483648 ve 2147483647 değerlerini içeren imzalı 32 bitlik tamsayılar temsil eder.The int type represents signed 32-bit integers with values between -2147483648 and 2147483647.
  • uintTür, 0 ile 4294967295 arasındaki değerlere sahip işaretsiz 32 bitlik tamsayılar temsil eder.The uint type represents unsigned 32-bit integers with values between 0 and 4294967295.
  • longTür,-9223372036854775808 ve 9223372036854775807 arasındaki değerlerle işaretli 64 bitlik tamsayılar temsil eder.The long type represents signed 64-bit integers with values between -9223372036854775808 and 9223372036854775807.
  • ulongTür, 0 ile 18446744073709551615 arasında değerler içeren işaretsiz 64 bitlik tamsayılar temsil eder.The ulong type represents unsigned 64-bit integers with values between 0 and 18446744073709551615.
  • charTür, 0 ile 65535 arasındaki değerlere sahip işaretsiz 16 bit tamsayılar temsil eder.The char type represents unsigned 16-bit integers with values between 0 and 65535. Türü için olası değerler kümesi char Unicode karakter kümesine karşılık gelir.The set of possible values for the char type corresponds to the Unicode character set. , char Aynı gösterimine sahip olsa da ushort , bir tür üzerinde izin verilen tüm işlemlere izin verilmez.Although char has the same representation as ushort, not all operations permitted on one type are permitted on the other.

Tam sayı türü birli ve ikili işleçler her zaman imzalanmış 32 bit duyarlık, imzasız 32 bit duyarlık, imzalı 64 bit duyarlık veya imzasız 64-bit duyarlık ile çalışır: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:

  • Birli + ve işleçler için, ~ işlenen türüne dönüştürülür, burada,,, T T int uint long ve ulong işlenenin tüm olası değerlerini tam olarak temsil edebilir.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. Daha sonra işlem türü duyarlık kullanılarak gerçekleştirilir T ve sonucun türü olur T .The operation is then performed using the precision of type T, and the type of the result is T.
  • Birli operatör için, - işlenen türüne dönüştürülür T , burada T ilki int ve long işlenenin tüm olası değerlerini tam olarak temsil edebilir.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. Daha sonra işlem türü duyarlık kullanılarak gerçekleştirilir T ve sonucun türü olur T .The operation is then performed using the precision of type T, and the type of the result is T. Birli - işleç türündeki işlenenlere uygulanamaz ulong .The unary - operator cannot be applied to operands of type ulong.
  • İkili,,,,,,,,,,,,, ve işleçleri için işlenen,,,, + - * / % & ^ | == != > < >= <= T T int uint long ve ulong her iki işlenenin olası tüm değerlerini tam olarak temsil eden,,, ve ' nin türü olarak dönüştürülür.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. Daha sonra işlem türü duyarlık kullanılarak gerçekleştirilir T ve sonucun türü T (veya bool ilişkisel işleçler için) olur.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). Bir işlenenin türü, long diğeri ise ikili işleçlerle türünden olması için izin verilmez 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.
  • İkili << ve işleçler için >> , sol işlenen türüne dönüştürülür, burada,,, T T int uint long ve ulong işlenenin tüm olası değerlerini tam olarak temsil edebilir.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. Daha sonra işlem türü duyarlık kullanılarak gerçekleştirilir T ve sonucun türü olur T .The operation is then performed using the precision of type T, and the type of the result is T.

charTür bir integral türü olarak sınıflandırıldı, ancak diğer integral türlerinden iki şekilde farklılık gösterir:The char type is classified as an integral type, but it differs from the other integral types in two ways:

  • Diğer türlerden türe örtük dönüştürme yok char .There are no implicit conversions from other types to the char type. Özellikle,, sbyte byte ve ushort türleri, türü kullanılarak tam olarak gösterilemeyen değer aralıklarına sahip olsa bile,, char veya ' den örtük dönüştürmeler sbyte byte ushort char yok.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.
  • Türün sabitlerinin char character_literal olarak yazılması gerekir veya bir tür dönüştürme ile birlikte integer_literal s olarak yazılmalıdır char .Constants of the char type must be written as character_literal s or as integer_literal s in combination with a cast to type char. Örneğin, (char)10 ile aynıdır '\x000A' .For example, (char)10 is the same as '\x000A'.

checkedVe unchecked işleçleri ve deyimleri, tamsayı türü aritmetik işlemler ve dönüştürmeler için taşma denetimini denetlemek için kullanılır (denetlenen ve işaretlenmemiş işleçler).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). Bir checked bağlamda, bir taşma derleme zamanı hatası üretir veya bir oluşturulmasına neden olur System.OverflowException .In a checked context, an overflow produces a compile-time error or causes a System.OverflowException to be thrown. Bir unchecked bağlamda, taşmalar yok sayılır ve hedef türüne uymayan tüm yüksek sıralı bitler atılır.In an unchecked context, overflows are ignored and any high-order bits that do not fit in the destination type are discarded.

Kayan nokta türleriFloating point types

C# iki kayan nokta türünü destekler: float ve double .C# supports two floating point types: float and double. floatVe double türleri, aşağıdaki değer kümelerini sağlayan 32 bitlik tek duyarlıklı ve 64-bit ÇIFT duyarlıklı IEEE 754 biçimlerini kullanarak temsil edilir: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:

  • Pozitif sıfır ve negatif sıfır.Positive zero and negative zero. Çoğu durumda, pozitif sıfır ve negatif sıfır değeri basit değer sıfır ile aynı şekilde davranır, ancak belirli işlemler iki (bölme işleci) arasında ayrım yapar.In most situations, positive zero and negative zero behave identically as the simple value zero, but certain operations distinguish between the two (Division operator).
  • Pozitif sonsuzluk ve negatif sonsuz.Positive infinity and negative infinity. Sonsuz değerleri, sıfır olmayan bir sayının sıfıra bölünmesi gibi işlemlerle üretilir.Infinities are produced by such operations as dividing a non-zero number by zero. Örneğin, 1.0 / 0.0 pozitif sonsuz sonucunu, -1.0 / 0.0 ise negatif sonsuz sonucunu verir.For example, 1.0 / 0.0 yields positive infinity, and -1.0 / 0.0 yields negative infinity.
  • Bir sayı değil değeri genellikle kısaltılmış Nan.The Not-a-Number value, often abbreviated NaN. NaN değerleri, sıfırın sıfıra bölünmesi gibi geçersiz kayan nokta işlemleriyle üretilir.NaNs are produced by invalid floating-point operations, such as dividing zero by zero.
  • Formun s * m * 2^e s 1 veya-1 olduğu ve m e belirli kayan nokta türü tarafından belirlendiği float 0 < m < 2^24 -149 <= e <= 104 double 0 < m < 2^53 -1075 <= e <= 970 , sıfır olmayan değerlerin sınırlı kümesi:, ve için ve için.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. Normalleştirilmemiş kayan noktalı sayılar geçerli sıfır olmayan değerler olarak kabul edilir.Denormalized floating-point numbers are considered valid non-zero values.

floatTür, yaklaşık 1.5 * 10^-45 olarak 3.4 * 10^38 7 basamaklı bir duyarlık ile arasında değişen değerleri temsil edebilir.The float type can represent values ranging from approximately 1.5 * 10^-45 to 3.4 * 10^38 with a precision of 7 digits.

doubleTür, 5.0 * 10^-324 1.7 × 10^308 15-16 basamaklı duyarlık ile yaklaşık olarak değişen değerleri temsil edebilir.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.

Bir ikili işlecin işlenenlerinden biri kayan nokta türünde ise, diğer işlenen bir integral türü veya kayan nokta türünde olmalıdır ve işlem aşağıdaki gibi değerlendirilir: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:

  • İşlenenden biri integral türünde ise, bu işlenen diğer işlenenin kayan nokta türüne dönüştürülür.If one of the operands is of an integral type, then that operand is converted to the floating-point type of the other operand.
  • Ardından, işlenenlerden biri tür ise double , diğer işlenen öğesine dönüştürülür double , işlem en az double Aralık ve duyarlık kullanılarak gerçekleştirilir ve sonucun türü double (veya bool ilişkisel işleçler için) olur.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).
  • Aksi takdirde, işlem en az float Aralık ve duyarlık kullanılarak gerçekleştirilir ve sonucun türü float (veya bool ilişkisel işleçler için) olur.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).

Atama işleçleri de dahil olmak üzere kayan nokta işleçleri hiçbir şekilde özel durum oluşturmaz.The floating-point operators, including the assignment operators, never produce exceptions. Bunun yerine, bazı durumlarda kayan nokta işlemleri, aşağıda açıklandığı gibi sıfır, sonsuz veya NaN üretir:Instead, in exceptional situations, floating-point operations produce zero, infinity, or NaN, as described below:

  • Kayan noktalı bir işlemin sonucu hedef biçim için çok küçükse, işlemin sonucu pozitif sıfır veya negatif sıfır olur.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.
  • Kayan noktalı bir işlemin sonucu hedef biçim için çok büyükse, işlemin sonucu pozitif sonsuzluk veya negatif sonsuzluk olur.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.
  • Kayan noktalı bir işlem geçersizse, işlemin sonucu NaN olur.If a floating-point operation is invalid, the result of the operation becomes NaN.
  • Kayan nokta işleminin işlenenlerinden biri veya ikisi birden NaN ise işlemin sonucu NaN olur.If one or both operands of a floating-point operation is NaN, the result of the operation becomes NaN.

Kayan nokta işlemleri, işlemin sonuç türünden daha yüksek bir duyarlıkla gerçekleştirilebilir.Floating-point operations may be performed with higher precision than the result type of the operation. Örneğin, bazı donanım mimarileri, daha fazla Aralık ve duyarlık içeren bir "genişletilmiş" veya "uzun çift" kayan nokta türünü destekler double ve bu daha yüksek duyarlık türünü kullanarak tüm kayan nokta işlemlerini örtülü olarak gerçekleştirir.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. Yalnızca performans açısından yüksek maliyetli, bu tür donanım mimarileri daha az duyarlılıkla kayan nokta işlemleri gerçekleştirmek için yapılabilir ve hem performans hem de duyarlık sağlamak için bir uygulama gerektirmek yerine, C# tüm kayan nokta işlemlerinde daha yüksek bir duyarlık türünün kullanılmasına izin verir.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. Daha kesin sonuçlar sunmaya kıyasla, bu nadiren de ölçülebilir etkileri vardır.Other than delivering more precise results, this rarely has any measurable effects. Bununla birlikte, x * y / z çarpma 'nın aralığın dışında kalan bir sonuç oluşturduğu double , ancak sonraki bölme geçici sonucu aralığa geri getiren bir double ifadenin, daha yüksek bir Aralık biçiminde değerlendirilme sonucu, sonsuz bir sonucun üretilmesine neden olabilir.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.

Ondalık türThe decimal type

decimalTürü, finansal ve parasal hesaplamalar için uygun olan 128 bitlik bir veri türüdür.The decimal type is a 128-bit data type suitable for financial and monetary calculations. decimalTür, 1.0 * 10^-28 yaklaşık 7.9 * 10^28 28-29 önemli basamağa kadar olan değerleri temsil edebilir.The decimal type can represent values ranging from 1.0 * 10^-28 to approximately 7.9 * 10^28 with 28-29 significant digits.

Türünde olan sınırlı değerler kümesi, decimal (-1)^s * c * 10^-e işaretin s 0 veya 1 olduğu, katsayısının c tarafından verildiği 0 <= *c* < 2^96 ve ölçeğin bu şekilde olduğu e bir formdur 0 <= e <= 28 . decimal Tür, imzalanmış sıfırları, sonsuz veya Nan 'yi desteklemez.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. Bir decimal , on ' un bir kuvvetine ölçeklenerek 96 bitlik bir tamsayı olarak temsil edilir.A decimal is represented as a 96-bit integer scaled by a power of ten. decimalSıfırdan küçük bir değeri olan s için 1.0m , değer tamamen 28 ondalık hanesiz, ancak başka bir değer değildir.For decimals with an absolute value less than 1.0m, the value is exact to the 28th decimal place, but no further. decimalMutlak değere eşit veya daha büyük bir değere sahip olan s için 1.0m değer 28 veya 29 haneye eşittir.For decimals with an absolute value greater than or equal to 1.0m, the value is exact to 28 or 29 digits. floatVe double veri türlerinin aksine, 0,1 gibi ondalık kesirli sayılar tam olarak decimal temsilde gösterilebilir.Contrary to the float and double data types, decimal fractional numbers such as 0.1 can be represented exactly in the decimal representation. floatVe double temsilleri bu tür sayılar genellikle sonsuz kesirler olduğundan, bu temsiller, yuvarlama hatalarına karşı daha açıktır.In the float and double representations, such numbers are often infinite fractions, making those representations more prone to round-off errors.

Bir ikili işlecin işlenenlerinden biri tür ise decimal , diğer işlenen bir integral türünde veya türünde olmalıdır decimal .If 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. İntegral türü işleneni varsa, decimal işlem gerçekleştirilmeden önce öğesine dönüştürülür.If an integral type operand is present, it is converted to decimal before the operation is performed.

Türündeki değerler üzerindeki bir işlemin sonucu, decimal tam bir sonucun hesaplanmasının (ölçeği her bir operatör için tanımlanan şekilde koruma) ve ardından temsili sığacak şekilde yuvarlama işleminin sonucu olacak.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. Sonuçlar en yakın gösterilemeyen değere yuvarlanır ve bir sonuç iki gösterilemeyen değere eşit bir şekilde yakınsa, en az önemli basamak konumunda çift sayı olan değere ("banker 'in yuvarlanması" olarak bilinir).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"). Sıfır sonucun her zaman 0 ve Ölçeği 0 olan bir imzası vardır.A zero result always has a sign of 0 and a scale of 0.

Ondalık aritmetik işlem mutlak değerden küçük veya buna eşit bir değer üretirse 5 * 10^-29 , işlemin sonucu sıfır olur.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. Bir decimal Aritmetik işlem, biçim için çok büyük bir sonuç üretirse decimal , bir oluşturulur System.OverflowException .If a decimal arithmetic operation produces a result that is too large for the decimal format, a System.OverflowException is thrown.

decimalTürün daha fazla duyarlığı ancak kayan nokta türlerinden daha küçük bir aralığı vardır.The decimal type has greater precision but smaller range than the floating-point types. Bu nedenle, kayan nokta türlerinden dönüşümler, decimal taşma özel durumları üretebilir ve ' den decimal kayan nokta türlerine dönüştürme duyarlık kaybına neden olabilir.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. Bu nedenlerden dolayı, kayan nokta türleri arasında örtük dönüştürmeler yoktur ve decimal Açık yayınlar olmadan, kayan nokta ve decimal işlenenleri aynı ifadede karıştırmak mümkün değildir.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 türüThe bool type

boolTür, Boolean mantıksal miktarları temsil eder.The bool type represents boolean logical quantities. Türü için olası değerler bool true ve ' dir false .The possible values of type bool are true and false.

Ve diğer türler arasında standart dönüştürme yok bool .No standard conversions exist between bool and other types. Özellikle, bool türü benzersiz ve integral türlerden ayrıdır ve bir bool değer tamsayı değer yerine kullanılamaz ve tam tersi de geçerlidir.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 ve C++ dillerinde, sıfır tamsayı veya kayan nokta değeri veya null bir işaretçi Boole değerine false , sıfır olmayan bir integral veya kayan nokta değerine dönüştürülebilir ya da null olmayan bir işaretçi Boole değerine dönüştürülebilir 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# dilinde, bu tür dönüştürmeler, tam olarak bir integral veya kayan nokta değeri sıfıra karşılaştırılarak ya da bir nesne başvurusunu açıkça karşılaştırarak gerçekleştirilir 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.

Numaralandırma türleriEnumeration types

Sabit listesi türü, adlandırılmış sabitleri olan ayrı bir türdür.An enumeration type is a distinct type with named constants. Her numaralandırma türünün,,,,,, veya olması gereken temel bir türü vardır byte sbyte short ushort int uint long ulong .Every enumeration type has an underlying type, which must be byte, sbyte, short, ushort, int, uint, long or ulong. Numaralandırma türünün değer kümesi, temel alınan türün değerleri kümesiyle aynıdır.The set of values of the enumeration type is the same as the set of values of the underlying type. Numaralandırma türünün değerleri, adlandırılmış sabitlerin değerleriyle sınırlı değildir.Values of the enumeration type are not restricted to the values of the named constants. Numaralandırma türleri, numaralandırma bildirimleri (enum bildirimleri) aracılığıyla tanımlanır.Enumeration types are defined through enumeration declarations (Enum declarations).

Null atanabilir türlerNullable types

Null yapılabilir bir tür, temel türünün tüm değerlerini ve ek bir null değeri temsil edebilir.A nullable type can represent all values of its underlying type plus an additional null value. Null yapılabilir bir tür yazılır T? , burada T temel alınan türdür.A nullable type is written T?, where T is the underlying type. Bu sözdizimi için toplu System.Nullable<T> ve iki form birbirinin yerine kullanılabilir.This syntax is shorthand for System.Nullable<T>, and the two forms can be used interchangeably.

Null yapılamayan bir değer türü , dışında bir değer türü System.Nullable<T> ve kendi kısaltması T? (herhangi bir) ve T null yapılamayan bir değer türü (yani, kısıtlama içeren herhangi bir tür parametresi) olarak kısıtlanan herhangi bir tür parametresi 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ür, T (tür parametresi kısıtlamaları) için değer türü kısıtlamasını belirtir, bu da null yapılabilir bir türün temel alınan türünün hiçbir null yapılamayan değer türü olabileceği anlamına gelir.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 yapılabilir bir türün temel alınan türü null yapılabilir bir tür veya başvuru türü olamaz.The underlying type of a nullable type cannot be a nullable type or a reference type. Örneğin, int?? ve string? geçersiz türlerdir.For example, int?? and string? are invalid types.

Null yapılabilir bir türün örneği T? , iki ortak salt okuma özelliklerine sahiptir:An instance of a nullable type T? has two public read-only properties:

  • HasValueTüründe bir özellikboolA HasValue property of type bool
  • ValueTüründe bir özellikTA Value property of type T

True olan bir örneği HasValue null olmayan bir örnek olarak kabul edilir.An instance for which HasValue is true is said to be non-null. Null olmayan bir örnek bilinen bir değer içerir ve Value Bu değeri döndürür.A non-null instance contains a known value and Value returns that value.

False olan bir örnek HasValue null olarak kabul edilir.An instance for which HasValue is false is said to be null. Null bir örnek tanımsız bir değere sahip.A null instance has an undefined value. Null bir örneği okumayı denemek Value bir öğesinin oluşturulmasına neden olur System.InvalidOperationException .Attempting to read the Value of a null instance causes a System.InvalidOperationException to be thrown. ValueNull yapılabilir bir örnek özelliğine erişme işlemi, sarmalama olarak adlandırılır.The process of accessing the Value property of a nullable instance is referred to as unwrapping.

Varsayılan oluşturucuya ek olarak, her Nullable türün T? türünde tek bir bağımsız değişken alan bir ortak Oluşturucusu vardır T .In addition to the default constructor, every nullable type T? has a public constructor that takes a single argument of type T. Türünde bir değer verildiğinde x T , formun Oluşturucu çağrısıGiven a value x of type T, a constructor invocation of the form

new T?(x)

özelliği için null olmayan bir örnek oluşturur T? Value x .creates a non-null instance of T? for which the Value property is x. Verili bir değer için null değer olmayan bir türün null olmayan bir örneğini oluşturma işlemi sarmalama olarak adlandırılır.The process of creating a non-null instance of a nullable type for a given value is referred to as wrapping.

Örtük dönüştürmeler, null değişmez değer 'den T? (null değişmez değer dönüştürmeleri) ve öğesinden T T? (örtük null yapılabilir dönüşümler) kullanılabilir.Implicit conversions are available from the null literal to T? (Null literal conversions) and from T to T? (Implicit nullable conversions).

Başvuru türleriReference types

Başvuru türü bir sınıf türü, arabirim türü, bir dizi türü veya temsilci türüdür.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
    ;

Başvuru türü değeri, _ nesne * olarak bilinen türün *örnek _ öğesine başvurudur.A reference type value is a reference to an instance _ of the type, the latter known as an _object**. Özel değer null tüm başvuru türleriyle uyumludur ve bir örneğin yokluğunu gösterir.The special value null is compatible with all reference types and indicates the absence of an instance.

Sınıf türleriClass types

Bir sınıf türü veri üyelerini (sabitler ve alanlar), işlev üyelerini (Yöntemler, özellikler, olaylar, Dizin oluşturucular, işleçler, örnek oluşturucular, Yıkıcılar ve statik oluşturucular) ve iç içe geçmiş türleri içeren bir veri yapısını tanımlar.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. Sınıf türleri, türetilmiş sınıfların temel sınıfları genişletebilen ve özelleştireceği bir mekanizma olan devralmayı destekler.Class types support inheritance, a mechanism whereby derived classes can extend and specialize base classes. Sınıf türlerinin örnekleri, object_creation_expression s (nesne oluşturma ifadeleri) kullanılarak oluşturulur.Instances of class types are created using object_creation_expression s (Object creation expressions).

Sınıf türleri sınıflardaaçıklanmıştır.Class types are described in Classes.

Önceden tanımlanmış bazı sınıf türleri, aşağıdaki tabloda açıklandığı gibi C# dilinde özel anlamlara sahiptir.Certain predefined class types have special meaning in the C# language, as described in the table below.

Sınıf türüClass type AçıklamaDescription
System.Object Diğer tüm türlerin Ultimate temel sınıfı.The ultimate base class of all other types. Bkz. nesne türü.See The object type.
System.String C# dilinin dize türü.The string type of the C# language. Dize türü' ne bakın.See The string type.
System.ValueType Tüm değer türlerinin temel sınıfı.The base class of all value types. Bkz. System. ValueType türü.See The System.ValueType type.
System.Enum Tüm sabit listesi türlerinin temel sınıfı.The base class of all enum types. Bkz. numaralandırmalar.See Enums.
System.Array Tüm dizi türlerinin temel sınıfı.The base class of all array types. Bkz. diziler.See Arrays.
System.Delegate Tüm temsilci türlerinin temel sınıfı.The base class of all delegate types. Bkz. Temsilciler.See Delegates.
System.Exception Tüm özel durum türlerinin temel sınıfı.The base class of all exception types. Bkz. özel durumlar.See Exceptions.

Nesne türüThe object type

objectSınıf türü, diğer tüm türlerin en son temel sınıfıdır.The object class type is the ultimate base class of all other types. C# içindeki her tür doğrudan veya dolaylı olarak object sınıf türünden türetilir.Every type in C# directly or indirectly derives from the object class type.

Anahtar sözcüğü, object önceden tanımlanmış sınıf için yalnızca bir diğer addır System.Object .The keyword object is simply an alias for the predefined class System.Object.

Dinamik türThe dynamic type

Gibi dynamic tür object herhangi bir nesneye başvurabilir.The dynamic type, like object, can reference any object. İşleçler türündeki ifadelere uygulandığında dynamic , çözüm program çalıştırılıncaya kadar ertelenir.When operators are applied to expressions of type dynamic, their resolution is deferred until the program is run. Bu nedenle, işleç başvurulan nesneye yasal olarak uygulanamazlar, derleme sırasında herhangi bir hata verilmez.Thus, if the operator cannot legally be applied to the referenced object, no error is given during compilation. Bunun yerine, işlecin çözümlenmesi çalışma zamanında başarısız olduğunda bir özel durum oluşturulur.Instead an exception will be thrown when resolution of the operator fails at run-time.

Amacı , dinamik bağlamadaayrıntılı olarak açıklanan dinamik bağlamaya izin versağlamaktır.Its purpose is to allow dynamic binding, which is described in detail in Dynamic binding.

dynamic , aşağıdaki gibi olarak aynı kabul edilir object :dynamic is considered identical to object except in the following respects:

  • Türündeki ifadelerde işlemler dynamic dinamik olarak bağlanabilir (dinamik bağlama).Operations on expressions of type dynamic can be dynamically bound (Dynamic binding).
  • dynamic object Her ikisi de aday ise, tür çıkarımı (tür çıkarımı) tercih edilir.Type inference (Type inference) will prefer dynamic over object if both are candidates.

Bu denklik nedeniyle aşağıdakiler şunları içerir:Because of this equivalence, the following holds:

  • object dynamic İle değiştirme sırasında aynı olan oluşturulmuş türler arasında ve arasında örtük bir kimlik dönüştürmesi vardır dynamic``objectThere is an implicit identity conversion between object and dynamic, and between constructed types that are the same when replacing dynamic with object
  • Ve ' de örtülü ve açık dönüştürmeler, ve object için de geçerlidir dynamic .Implicit and explicit conversions to and from object also apply to and from dynamic.
  • İle değiştirme sırasında aynı olan yöntem imzaları dynamic object aynı imza olarak değerlendirilirMethod signatures that are the same when replacing dynamic with object are considered the same signature
  • Tür, dynamic çalışma zamanında ayırt edilemez object .The type dynamic is indistinguishable from object at run-time.
  • Türün bir ifadesi dynamic , dinamik ifade olarak adlandırılır.An expression of the type dynamic is referred to as a dynamic expression.

Dize türüThe string type

stringTürü, doğrudan öğesinden devralan bir Sealed Class türüdür object .The string type is a sealed class type that inherits directly from object. stringSınıfın örnekleri Unicode karakter dizelerini temsil eder.Instances of the string class represent Unicode character strings.

stringTürün değerleri dize sabit değerleri (dize sabit değerleri) olarak yazılabilir.Values of the string type can be written as string literals (String literals).

Anahtar sözcüğü, string önceden tanımlanmış sınıf için yalnızca bir diğer addır System.String .The keyword string is simply an alias for the predefined class System.String.

Arabirim türleriInterface types

Arabirim, bir sözleşmeyi tanımlar.An interface defines a contract. Arabirim uygulayan bir sınıf veya yapı, sözleşmesine uymalıdır.A class or struct that implements an interface must adhere to its contract. Bir arabirim birden çok temel arabirimden devralınabilir ve bir sınıf ya da yapı birden çok arabirim uygulayabilir.An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.

Arabirim türleri arabirimlerdeaçıklanmıştır.Interface types are described in Interfaces.

Dizi türleriArray types

Dizi, hesaplanan dizinler üzerinden erişilen sıfır veya daha fazla değişken içeren bir veri yapısıdır.An array is a data structure that contains zero or more variables which are accessed through computed indices. Bir dizide bulunan değişkenler, dizi öğeleri de denir, hepsi aynı türdür ve bu tür dizinin öğe türü olarak adlandırılır.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.

Dizi türleri dizileriçinde açıklanmıştır.Array types are described in Arrays.

Temsilci türleriDelegate types

Bir temsilci, bir veya daha fazla yönteme başvuran bir veri yapısıdır.A delegate is a data structure that refers to one or more methods. Örnek yöntemleri için de ilgili nesne örneklerine başvurur.For instance methods, it also refers to their corresponding object instances.

C veya C++ içindeki bir temsilcinin en yakın eşdeğeri bir işlev işaretçisidir, ancak bir işlev işaretçisi yalnızca statik işlevlere başvurabilir, bir temsilci hem statik hem de örnek yöntemlerine başvurabilir.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. İkinci durumda, temsilci yalnızca metodun giriş noktasına bir başvuru değil, aynı zamanda yöntemi çağırmak için bir nesne örneğine de bir başvuru içerir.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.

Temsilci türleri Temsilcilerdeaçıklanmıştır.Delegate types are described in Delegates.

Kutulama ve kutudan çıkarmaBoxing and unboxing

Kutulama ve kutudan çıkarma kavramı C# tür sistemine göre yapılır.The concept of boxing and unboxing is central to C#'s type system. Value_type s ve reference_type s arasında bir köprü sağlar. Bu, value_type herhangi bir değerin türe ve türüne dönüştürülmesine izin verir object .It provides a bridge between value_type s and reference_type s by permitting any value of a value_type to be converted to and from type object. Kutulama ve kutudan çıkarma, herhangi bir türde bir değer olan tür sisteminin birleştirilmiş bir görünümünü, sonunda bir nesne olarak kabul edilebilir.Boxing and unboxing enables a unified view of the type system wherein a value of any type can ultimately be treated as an object.

Paketleme dönüştürmeleriBoxing conversions

Kutulama dönüştürme bir value_type örtülü olarak bir reference_type dönüştürülmesine izin verir.A boxing conversion permits a value_type to be implicitly converted to a reference_type. Aşağıdaki kutulama dönüştürmeleri mevcuttur:The following boxing conversions exist:

  • Value_type yazın object .From any value_type to the type object.
  • Value_type yazın System.ValueType .From any value_type to the type System.ValueType.
  • Herhangi bir non_nullable_value_type value_type tarafından uygulanan interface_type .From any non_nullable_value_type to any interface_type implemented by the value_type.
  • Herhangi bir nullable_type , nullable_type temel alınan türü tarafından uygulanan interface_type .From any nullable_type to any interface_type implemented by the underlying type of the nullable_type.
  • Enum_type yazın System.Enum .From any enum_type to the type System.Enum.
  • Nullable_type , temel enum_type türüne sahip olan herhangi bir System.Enum .From any nullable_type with an underlying enum_type to the type System.Enum.
  • Bir tür parametresindeki örtük dönüştürmenin, çalışma zamanında bir değer türünden bir başvuru türüne (tür parametreleri Içeren örtük dönüştürmeler) dönüştürülmesini istiyorsanız kutulama dönüştürmesi olarak yürütüleceğini unutmayın.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).

Bir non_nullable_value_type değerini kutulama bir nesne örneği ayırmayı ve non_nullable_value_type değerini bu örneğe kopyalamayı içerir.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.

Bir nullable_type bir değeri null kutulama değeri (ise) ise null bir başvuru üretir HasValue false veya temel alınan değeri başka bir şekilde sarmalamayı geri Kutulamadan elde edin.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.

Bir non_nullable_value_type bir değeri kutulama gerçek süreci, bir genel paketleme sınıfının mevcut olması halinde, aşağıdaki gibi olarak da gösterildiği gibi davranan en iyi şekilde açıklanmıştır: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üründeki bir değerin kutulenmesi v T , artık ifadeyi yürütmekten new Box<T>(v) ve sonuç örneğini türünde bir değer olarak döndürmekten oluşur 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. Bu nedenle, deyimlerThus, the statements

int i = 123;
object box = i;

kavramsal olarak karşılık gelenconceptually correspond to

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

Yukarıdaki gibi bir paketleme sınıfı Box<T> aslında yoktur ve paketlenmiş değerin dinamik türü aslında bir sınıf türü değildir.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. Bunun yerine, türü paketlenmiş bir değer T dinamik türe sahiptir T ve işleci kullanan dinamik bir tür denetimi is yalnızca başvuru türünde olabilir T .Instead, 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. Örneğin,For example,

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

, konsolundaki "" dizesini çıktısını alır Box contains an int .will output the string "Box contains an int" on the console.

Kutulama dönüştürme, kutulanmış değerin bir kopyasını yapmayı gerektirir.A boxing conversion implies making a copy of the value being boxed. Bu, bir reference_type türüne dönüşümden farklıdır object , burada değer aynı örneğe başvurmaya devam eder ve yalnızca daha az türetilmiş tür olarak kabul edilir object .This 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. Örneğin, bildirim verildiğindeFor example, given the declaration

struct Point
{
    public int x, y;

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

Aşağıdaki deyimlerthe following statements

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

, ' ın atamasında oluşan örtük paketleme işlemi p box değerinin kopyalanmasına neden olduğundan, konsolundaki 10 değerini çıktı 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 Bunun yerine bir olarak bildirildiği için, 20 değeri çıkış olur, çünkü p box aynı örneğe başvurmalıdır.Had Point been declared a class instead, the value 20 would be output because p and box would reference the same instance.

Kutudan çıkarma dönüştürmeleriUnboxing conversions

Kutudan çıkarma dönüştürmesi, bir reference_type açıkça bir value_type dönüştürülmesine izin verir.An unboxing conversion permits a reference_type to be explicitly converted to a value_type. Aşağıdaki kutudan çıkarma dönüştürmeleri mevcuttur:The following unboxing conversions exist:

  • Türünden object herhangi bir value_type.From the type object to any value_type.
  • Türünden System.ValueType herhangi bir value_type.From the type System.ValueType to any value_type.
  • Herhangi bir interface_type interface_type uygulayan non_nullable_value_type .From any interface_type to any non_nullable_value_type that implements the interface_type.
  • Herhangi bir interface_type temel alınan türü interface_type uygulayan nullable_type .From any interface_type to any nullable_type whose underlying type implements the interface_type.
  • Türünden System.Enum herhangi bir enum_type.From the type System.Enum to any enum_type.
  • Türünden System.Enum herhangi bir nullable_type temel enum_type.From the type System.Enum to any nullable_type with an underlying enum_type.
  • Bir tür parametresine açık dönüştürme, bir başvuru türünden bir değer türüne (Açık dinamik dönüştürmeler) dönüştürme sona erdiğinde, bir paket açma dönüştürmesi olarak yürütülür.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).

Bir non_nullable_value_type kutudan çıkarma işlemi, nesne örneğinin verilen non_nullable_value_type paketlenmiş bir değer olup olmadığını kontrol ederek değeri örnekten dışarı kopyalamaktan oluşur.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.

Bir nullable_type kutudan çıkarma, kaynak işleneni ise nullable_type null değerini null veya nullable_type temel alınan türüne nesne örneğini kutudan çıkarma sonucunu, aksi halde üretir.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.

Önceki bölümde açıklanan sanal paketleme sınıfına başvurarak, bir nesnenin bir value_type kutudan çıkarılmasının, box T ifadenin yürütülmesinin ardından oluşur ((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. Bu nedenle, deyimlerThus, the statements

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

kavramsal olarak karşılık gelenconceptually correspond to

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

Belirli bir non_nullable_value_type çalışma zamanında başarılı olmak için bir kutudan çıkarma dönüştürmesi için, kaynak işlenenin değeri, bu non_nullable_value_type paketlenmiş bir değere başvuru olmalıdır.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. Kaynak işleneni ise null , bir oluşturulur System.NullReferenceException .If the source operand is null, a System.NullReferenceException is thrown. Kaynak işleneni uyumsuz bir nesneye başvuru ise, bir System.InvalidCastException oluşturulur.If the source operand is a reference to an incompatible object, a System.InvalidCastException is thrown.

Belirli bir nullable_type çalışma zamanında başarılı olmak için bir kutudan çıkarma dönüştürmesi için, kaynak işlenenin değeri ya da null nullable_type temeldeki non_nullable_value_type kutulanmış bir değere başvuru olmalıdır.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. Kaynak işleneni uyumsuz bir nesneye başvuru ise, bir System.InvalidCastException oluşturulur.If the source operand is a reference to an incompatible object, a System.InvalidCastException is thrown.

Oluşturulmuş türlerConstructed types

Genel tür bildirimi, tek başına, tür bağımsız değişkenleri uygulama yoluyla birçok farklı tür oluşturmak için bir "Blueprint" olarak kullanılan *ilişkisiz genel tür _ ' i belirtir.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*_. Tür bağımsız değişkenleri, < > genel türün adının hemen ardından gelen açılı ayraç (ve) içinde yazılır.The type arguments are written within angle brackets (< and >) immediately following the name of the generic type. En az bir tür bağımsız değişkeni içeren bir türe oluşturulmuş tür denir.A type that includes at least one type argument is called a constructed type. Oluşturulmuş bir tür, bir tür adının görünebileceği dilde çoğu yerde kullanılabilir.A constructed type can be used in most places in the language in which a type name can appear. İlişkisiz genel tür yalnızca bir _typeof_expression * (typeof işleci) içinde kullanılabilir.An unbound generic type can only be used within a _typeof_expression* (The typeof operator).

Oluşturulan türler, ifadelerde basit adlar (basit adlar) veya bir üyeye (üye erişimi) erişimi olarak da kullanılabilir.Constructed types can also be used in expressions as simple names (Simple names) or when accessing a member (Member access).

Bir namespace_or_type_name değerlendirildiğinde, yalnızca doğru sayıda tür parametrelerine sahip genel türler kabul edilir.When a namespace_or_type_name is evaluated, only generic types with the correct number of type parameters are considered. Bu nedenle, türlerin tür parametrelerine sahip olduğu sürece farklı türleri tanımlamak için aynı tanımlayıcıyı kullanmak mümkündür.Thus, it is possible to use the same identifier to identify different types, as long as the types have different numbers of type parameters. Bu, genel ve genel olmayan sınıfları aynı programda karıştırdığınızda yararlı olur: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 , doğrudan tür parametreleri belirtmese de, oluşturulmuş bir türü tanımlayabilir.A type_name might identify a constructed type even though it doesn't specify type parameters directly. Bu, bir türün genel sınıf bildiriminde iç içe kullanıldığı ve kapsayan bildirimin örnek türünün, ad araması için örtük olarak kullanıldığı bir durum olabilir (genel sınıflarda Iç içe türler):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
}

Güvenli olmayan kodda, oluşturulmuş bir tür unmanaged_type (işaretçi türleri) olarak kullanılamaz.In unsafe code, a constructed type cannot be used as an unmanaged_type (Pointer types).

Tür bağımsız değişkenleriType arguments

Bir tür bağımsız değişkeni listesindeki her bağımsız değişken yalnızca bir türdür.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
    ;

Güvenli olmayan kodda (güvenli olmayan kod), bir type_argument işaretçi türü olmayabilir.In unsafe code (Unsafe code), a type_argument may not be a pointer type. Her tür bağımsız değişkeni, karşılık gelen tür parametresindeki (tür parametresi kısıtlamaları) tüm kısıtlamalara uymalıdır.Each type argument must satisfy any constraints on the corresponding type parameter (Type parameter constraints).

Açık ve kapalı türlerOpen and closed types

Tüm türler *Açık türler _ veya _ kapalı türler * olarak sınıflandırılabilirler.All types can be classified as either open types _ or _closed types**. Açık tür, tür parametrelerini içeren bir türdür.An open type is a type that involves type parameters. Daha ayrıntılı belirtmek gerekirse:More specifically:

  • Bir tür parametresi bir açık türü tanımlar.A type parameter defines an open type.
  • Bir dizi türü, ve yalnızca kendi öğe türü açık bir tür ise açık bir türdür.An array type is an open type if and only if its element type is an open type.
  • Oluşturulmuş bir tür, yalnızca bir veya daha fazla bağımsız değişkeni açık bir tür ise açık bir türdür.A constructed type is an open type if and only if one or more of its type arguments is an open type. Oluşturulmuş iç içe bir tür, yalnızca bir veya daha fazla tür bağımsız değişkeni ya da kapsayan tür bağımsız değişkenleri bir açık tür ise açık bir türdür.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.

Kapalı bir tür, açık tür olmayan bir türdür.A closed type is a type that is not an open type.

Çalışma zamanında, genel bir tür bildirimi içindeki tüm kod, genel bildirime tür bağımsız değişkenleri uygulanarak oluşturulan kapalı oluşturulmuş bir tür bağlamında yürütülür.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. Genel tür içindeki her tür parametresi, belirli bir çalışma zamanı türüne bağlanır.Each type parameter within the generic type is bound to a particular run-time type. Tüm deyimlerin ve ifadelerin çalışma zamanı işleme her zaman kapalı türlerle oluşur ve açık türler yalnızca derleme zamanı işleme sırasında oluşur.The run-time processing of all statements and expressions always occurs with closed types, and open types occur only during compile-time processing.

Her kapatılan oluşturulmuş türün kendi statik değişkenleri kümesi vardır ve bu, başka bir kapalı oluşturulmuş türle paylaşılmaz.Each closed constructed type has its own set of static variables, which are not shared with any other closed constructed types. Çalışma zamanında açık bir tür olmadığından, bir açık türle ilişkili statik değişken yoktur.Since an open type does not exist at run-time, there are no static variables associated with an open type. Aynı ilişkisiz genel türden oluşturulmuşsa ve ilgili tür bağımsız değişkenleri aynı türde ise, bu iki adet oluşturulmuş tür oluşturulur.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.

Bağlı ve ilişkisiz türlerBound and unbound types

*İlişkisiz tür _ terimi genel olmayan bir tür veya ilişkisiz genel bir tür anlamına gelir.The term *unbound type _ refers to a non-generic type or an unbound generic type. _ Bağlantılı tür* terimi genel olmayan bir türe veya oluşturulmuş bir türe başvurur.The term _ bound type* refers to a non-generic type or a constructed type.

İlişkisiz bir tür, bir tür bildirimiyle belirtilen varlığı ifade eder.An unbound type refers to the entity declared by a type declaration. İlişkisiz genel tür bir tür değildir ve bir değişken, bağımsız değişken veya dönüş değeri ya da bir temel tür olarak kullanılamaz.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. İlişkisiz genel bir türün başvurabilecebileceği tek yapı, typeof ifadedir (typeof işleci).The only construct in which an unbound generic type can be referenced is the typeof expression (The typeof operator).

Yer çağıran kısıtlamalarSatisfying constraints

Oluşturulmuş bir tür veya genel yönteme başvurulduğunda, sağlanan tür bağımsız değişkenleri genel tür veya yöntemde (tür parametresi kısıtlamaları) belirtilen tür parametresi kısıtlamalarına göre denetlenir.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). Her where yan tümce için, A adlandırılmış tür parametresine karşılık gelen tür bağımsız değişkeni her bir kısıtlamaya göre aşağıdaki gibi denetlenir:For each where clause, the type argument A that corresponds to the named type parameter is checked against each constraint as follows:

  • Kısıtlama bir sınıf türü, bir arabirim türü veya bir tür parametresi ise, C kısıtlamada görünen herhangi bir tür parametresi için sağlanan tür bağımsız değişkenleriyle bu kısıtlamayı temsil edelim.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. Kısıtlamayı karşılamak için, türün türüne dönüştürülebilir olması gerekir, aşağıdakilerden A C biri:To satisfy the constraint, it must be the case that type A is convertible to type C by one of the following:
  • Kısıtlama başvuru türü kısıtlamasıdır ( class ), türün aşağıdakilerden A birini karşılaması gerekir:If the constraint is the reference type constraint (class), the type A must satisfy one of the following:
    • A bir arabirim türü, sınıf türü, temsilci türü veya dizi türüdür.A is an interface type, class type, delegate type or array type. System.ValueType System.Enum Bu kısıtlamayı karşılayan başvuru türleri ve olduğunu unutmayın.Note that System.ValueType and System.Enum are reference types that satisfy this constraint.
    • A , bir başvuru türü olarak bilinen bir tür parametresidir (tür parametresi kısıtlamaları).A is a type parameter that is known to be a reference type (Type parameter constraints).
  • Kısıtlama değer türü kısıtlamadır ( struct ), türün aşağıdakilerden A birini karşılaması gerekir:If the constraint is the value type constraint (struct), the type A must satisfy one of the following:
    • A bir struct türü veya Enum türüdür, ancak null yapılabilir bir tür değildir.A is a struct type or enum type, but not a nullable type. System.ValueTypeVe System.Enum Bu kısıtlamayı karşılamayan başvuru türleri olduğunu unutmayın.Note that System.ValueType and System.Enum are reference types that do not satisfy this constraint.
    • A değer türü kısıtlamasına (tür parametresi kısıtlamaları) sahip bir tür parametresidir.A is a type parameter having the value type constraint (Type parameter constraints).
  • Kısıtlama Oluşturucu kısıtlamasıdır new() , türün A olmaması abstract ve ortak parametresiz bir oluşturucuya sahip olması gerekir.If the constraint is the constructor constraint new(), the type A must not be abstract and must have a public parameterless constructor. Aşağıdakilerden biri doğruysa, bu karşılanır:This is satisfied if one of the following is true:

Bir veya daha fazla tür parametresi kısıtlaması verilen tür bağımsız değişkenleri tarafından karşılanmıyorsa, derleme zamanı hatası oluşur.A compile-time error occurs if one or more of a type parameter's constraints are not satisfied by the given type arguments.

Tür parametreleri devralınmadığından, kısıtlamalar hiçbir şekilde devralınmaz.Since type parameters are not inherited, constraints are never inherited either. Aşağıdaki örnekte, D T T temel sınıf tarafından uygulanan kısıtlamayı karşılayan şekilde tür parametresinde kısıtlamayı belirtmesi gerekir 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>. Buna karşılık, E için uygulayan sınıf bir kısıtlama belirtmemelidir List<T> IEnumerable T .In 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>> {...}

Tür parametreleriType parameters

Tür parametresi, parametrenin çalışma zamanında bağlandığı bir değer türü veya başvuru türü atayarak bir tanıtıcıdır.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
    ;

Bir tür parametresi birçok farklı gerçek tür bağımsız değişkeni ile örneklenmiş olduğundan, tür parametrelerinin farklı işlemleri ve kısıtlamaları diğer türlerden farklıdır.Since a type parameter can be instantiated with many different actual type arguments, type parameters have slightly different operations and restrictions than other types. Bu modüller şunlardır:These include:

Tür olarak, tür parametreleri yalnızca derleme zamanı yapısıdır.As a type, type parameters are purely a compile-time construct. Çalışma zamanında, her tür parametresi genel tür bildirimine bir tür bağımsız değişkeni sağlanarak belirtilen bir çalışma zamanı türüne bağlanır.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. Bu nedenle, bir tür parametresiyle belirtilen değişkenin türü, çalışma zamanında, Kapalı oluşturulmuş bir tür (açık ve kapalı türler) olur.Thus, the type of a variable declared with a type parameter will, at run-time, be a closed constructed type (Open and closed types). Tüm deyimlerin ve tür parametreleri içeren ifadelerin çalışma zamanı yürütmesi, bu parametre için tür bağımsız değişkeni olarak sağlanan gerçek türü kullanır.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.

İfade ağacı türleriExpression tree types

*İfade ağaçları _ lambda ifadelerinin yürütülebilir kod yerine veri yapıları olarak gösterilmesine izin verir.*Expression trees _ permit lambda expressions to be represented as data structures instead of executable code. İfade ağaçları, formun ** System.Linq.Expressions.Expression<D> D herhangi bir temsilci türü olduğu, ' nin _ Expression Tree Types * değerleridir.Expression trees are values of _ expression tree types* of the form System.Linq.Expressions.Expression<D>, where D is any delegate type. Bu şartın geri kalanında, bu türlere kısayol kullanarak başvuracağız Expression<D> .For the remainder of this specification we will refer to these types using the shorthand Expression<D>.

Bir lambda ifadesinden bir temsilci türüne dönüştürme varsa D , ifade ağaç türüne de bir dönüştürme de vardır 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>. Bir lambda ifadesinin bir temsilci türüne dönüştürülmesi, lambda ifadesinin yürütülebilir koduna başvuran bir temsilci oluşturduğunda, bir ifade ağacı türüne dönüştürme lambda ifadesinin ifade ağacı gösterimini oluşturur.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.

İfade ağaçları, lambda ifadelerinin verimli bellek içi veri temsilleridir ve lambda ifadesinin yapısını saydam ve açık hale getirir.Expression trees are efficient in-memory data representations of lambda expressions and make the structure of the lambda expression transparent and explicit.

Yalnızca bir temsilci türü gibi D , Expression<D> ile aynı olan parametre ve dönüş türlerine sahip olduğu söylenir 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.

Aşağıdaki örnek, hem yürütülebilir kod hem de bir ifade ağacı olarak bir lambda ifadesini temsil eder.The following example represents a lambda expression both as executable code and as an expression tree. ' A bir dönüştürme olduğundan Func<int,int> , şu şekilde bir dönüştürme de mevcuttur 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

Bu atamaları takip eden temsilci, del döndüren bir yönteme başvurur x + 1 ve ifade ağacı exp ifadeyi tanımlayan bir veri yapısına başvurur 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.

Genel türün tam tanımı ve Expression<D> bir lambda ifadesi bir ifade ağacı türüne dönüştürüldüğünde bir ifade ağacı oluşturmak için kesin kurallar, her ikisi de bu belirtim kapsamının dışındadır.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.

Açık hale getirmek için iki şey önemlidir:Two things are important to make explicit:

  • Tüm lambda ifadeleri ifade ağaçlarına dönüştürülemez.Not all lambda expressions can be converted to expression trees. Örneğin, deyim gövdeleriyle lambda ifadeleri ve atama ifadeleri içeren lambda ifadeleri temsil edilemez.For instance, lambda expressions with statement bodies, and lambda expressions containing assignment expressions cannot be represented. Bu durumlarda, bir dönüştürme hala vardır ancak derleme zamanında başarısız olur.In these cases, a conversion still exists, but will fail at compile-time. Bu özel durumlar anonim işlev dönüştürmelerindeayrıntılıdır.These exceptions are detailed in Anonymous function conversions.

  • Expression<D>``Compiletüründe bir temsilci üreten bir örnek yöntemi sunar D :Expression<D> offers an instance method Compile which produces a delegate of type D:

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

    Bu temsilciyi çağırmak, ifade ağacının gösterdiği kodun yürütülmesine neden olur.Invoking this delegate causes the code represented by the expression tree to be executed. Bu nedenle, yukarıdaki tanımlar, del ve del2 eşdeğerdir ve aşağıdaki iki deyim aynı etkiye sahip olacaktır: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);
    

    Bu kodu yürüttükten sonra i1 ve i2 her ikisi de değerine sahip olur 2 .After executing this code, i1 and i2 will both have the value 2.