Aracılığıyla paylaş


8 Tür

8.1 Genel

C# dilinin türleri iki ana kategoriye ayrılır: başvuru türleri ve değer türleri. Hem değer türleri hem de başvuru türleri, bir veya daha fazla tür parametresi alan genel türler olabilir. Tür parametreleri hem değer türlerini hem de başvuru türlerini belirleyebilir.

type
    : reference_type
    | value_type
    | type_parameter
    | pointer_type     // unsafe code support
    ;

pointer_type (§23.3) yalnızca güvenli olmayan kodda (§23) kullanılabilir.

Değer türleri, değer türlerinin değişkenlerinin verilerini doğrudan içermesi nedeniyle başvuru türlerinden farklılık gösterirken, başvuru türlerinin değişkenleri kendi verilerine başvuru depolar ve ikincisi nesne olarak bilinir. Başvuru türleriyle, iki değişkenin aynı nesneye başvurması ve bu nedenle bir değişkendeki işlemlerin diğer değişken tarafından başvuruda bulunan nesneyi etkilemesi mümkündür. Değer türleriyle, değişkenlerin her biri kendi veri kopyasına sahiptir ve biri üzerindeki işlemlerin diğerini etkilemesi mümkün değildir.

Not: Bir değişken bir başvuru veya çıkış parametresi olduğunda, kendi depolama alanı yoktur, ancak başka bir değişkenin depolamasına başvurur. Bu durumda ref veya out değişkeni, farklı bir değişken için değil, başka bir değişken için etkili bir diğer addır. son not

C#'nin tür sistemi, herhangi bir türde bir değerin nesne olarak ele alınabilmesi için birleştirilir. C# içindeki her tür doğrudan veya dolaylı olarak sınıf türünden object türetilir ve object tüm türlerin nihai temel sınıfıdır. Başvuru türlerinin değerleri yalnızca türü objectolarak görüntülenerek nesne olarak değerlendirilir. Değer türlerinin değerleri, kutulama ve kutu açma işlemleri (§8.3.13) gerçekleştirilerek nesne olarak değerlendirilir.

Kolaylık sağlamak için, bu belirtim boyunca, bazı kitaplık türü adları tam ad nitelikleri kullanılmadan yazılır. Daha fazla bilgi için §C.5 adresine bakın.

8.2 Başvuru türleri

8.2.1 Genel

Başvuru türü bir sınıf türü, arabirim türü, dizi türü, temsilci türü veya türdür dynamic . Boş değer atanamayan her başvuru türü için, türün adına eklenerek ? belirtilen karşılık gelen bir null atanabilir başvuru türü vardır.

reference_type
    : non_nullable_reference_type
    | nullable_reference_type
    ;

non_nullable_reference_type
    : class_type
    | interface_type
    | array_type
    | delegate_type
    | 'dynamic'
    ;

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

interface_type
    : type_name
    ;

array_type
    : non_array_type rank_specifier+
    ;

non_array_type
    : value_type
    | class_type
    | interface_type
    | delegate_type
    | 'dynamic'
    | type_parameter
    | pointer_type      // unsafe code support
    ;

rank_specifier
    : '[' ','* ']'
    ;

delegate_type
    : type_name
    ;

nullable_reference_type
    : non_nullable_reference_type nullable_type_annotation
    ;

nullable_type_annotation
    : '?'
    ;

pointer_type yalnızca güvenli olmayan kodda (§23.3) kullanılabilir. nullable_reference_type daha ayrıntılı olarak §8.9'da ele alınılmaktadır.

Başvuru türü değeri, türün bir örneğine başvurudur ve ikincisi nesne olarak bilinir. Özel değer null tüm başvuru türleriyle uyumludur ve bir örneğin yokluğunu gösterir.

8.2.2 Sınıf türleri

Sınıf türü, veri üyeleri (sabitler ve alanlar), işlev üyeleri (yöntemler, özellikler, olaylar, dizin oluşturucular, işleçler, örnek oluşturucuları, sonlandırıcılar ve statik oluşturucular) ve iç içe türler içeren bir veri yapısı tanımlar. Sınıf türleri, türetilmiş sınıfların temel sınıfları genişletebildiği ve uzmanlaşabileceği bir mekanizma olan devralmayı destekler. Sınıf türlerinin örnekleri object_creation_expressionkullanılarak oluşturulur (§12.8.17.2).

Sınıf türleri §15'te açıklanmıştır.

Bazı önceden tanımlanmış sınıf türleri, aşağıdaki tabloda açıklandığı gibi C# dilinde özel bir anlama sahiptir.

Sınıf türü Açıklama
System.Object Diğer tüm türlerin nihai temel sınıfı. Bkz . §8.2.3.
System.String C# dilinin dize türü. Bkz . §8.2.5.
System.ValueType Tüm değer türlerinin temel sınıfı. Bkz . §8.3.2.
System.Enum Tüm enum türlerin temel sınıfı. Bkz. §19.5.
System.Array Tüm dizi türlerinin temel sınıfı. Bkz . §17.2.2.
System.Delegate Tüm delegate türlerin temel sınıfı. Bkz. §20.1.
System.Exception Tüm özel durum türlerinin temel sınıfı. Bkz. §21.3.

8.2.3 Nesne türü

object Sınıf türü, diğer tüm türlerin nihai temel sınıfıdır. C# içindeki her tür doğrudan veya dolaylı olarak sınıf türünden object türetilir.

anahtar sözcüğü object , önceden tanımlanmış sınıfı System.Objectiçin bir diğer addır.

8.2.4 Dinamik tür

dynamic gibi objectbir tür herhangi bir nesneye başvurabilir. türündeki dynamicifadelere işlemler uygulandığında, program çalıştırana kadar çözümlemeleri ertelenecek. Bu nedenle, işlem başvurulan nesneye yasal olarak uygulanamazsa, derleme sırasında hata verilmez. Bunun yerine, çalışma zamanında işlemin çözümü başarısız olduğunda bir özel durum oluşturulur.

Türü dynamic daha ayrıntılı olarak §8.7 ve dinamik bağlama ise §12.3.1'de açıklanmıştır.

8.2.5 Dize türü

türü string , doğrudan öğesinden objectdevralınan korumalı bir sınıf türüdür. sınıfının örnekleri string Unicode karakter dizelerini temsil eder.

Türün string değerleri dize değişmez değerleri (§6.4.5.6) olarak yazılabilir.

anahtar sözcüğü string , önceden tanımlanmış sınıfı System.Stringiçin bir diğer addır.

8.2.6 Arabirim türleri

Arabirim bir sözleşme tanımlar. Arabirim uygulayan bir sınıf veya yapı, sözleşmesine uymalıdır. Bir arabirim birden çok temel arabirimden devralabilir ve bir sınıf veya yapı birden çok arabirim uygulayabilir.

Arabirim türleri §18'de açıklanmıştır.

8.2.7 Dizi türleri

Dizi, hesaplanan dizinler aracılığıyla erişilen sıfır veya daha fazla değişken içeren bir veri yapısıdır. Dizinin öğeleri olarak da adlandırılan bir dizideki değişkenlerin tümü aynı türdedir ve bu tür dizinin öğe türü olarak adlandırılır.

Dizi türleri §17'de açıklanmıştır.

8.2.8 Temsilci türleri

Temsilci, bir veya daha fazla yönteme başvuran bir veri yapısıdır. Örneğin yöntemler, bunlara karşılık gelen nesne örneklerine de başvurur.

Not: C veya C++ içindeki bir temsilcinin en yakın eşdeğeri bir işlev işaretçisidir, ancak işlev işaretçisi yalnızca statik işlevlere başvurabilirken, temsilci hem statik hem de örnek yöntemlerine başvurabilir. İkinci durumda, temsilci yalnızca yöntemin giriş noktasına bir başvuru değil, aynı zamanda yönteminin çağrılacağı nesne örneğine de başvuru depolar. son not

Temsilci türleri §20'de açıklanmıştır.

8.3 Değer türleri

8.3.1 Genel

Değer türü bir yapı türü veya numaralandırma türüdür. C# basit türler olarak adlandırılan önceden tanımlanmış yapı türleri kümesi sağlar. Basit türler anahtar sözcüklerle tanımlanır.

value_type
    : non_nullable_value_type
    | nullable_value_type
    ;

non_nullable_value_type
    : struct_type
    | enum_type
    ;

struct_type
    : type_name
    | simple_type
    | tuple_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'
    ;

tuple_type
    : '(' tuple_type_element (',' tuple_type_element)+ ')'
    ;
    
tuple_type_element
    : type identifier?
    ;
    
enum_type
    : type_name
    ;

nullable_value_type
    : non_nullable_value_type nullable_type_annotation
    ;

Başvuru türünün değişkenlerinden farklı olarak, değer türündeki bir değişken değeri yalnızca değer null türü null atanabilir bir değer türündeyse (§8.3.12) içerebilir. Null değer atanamayan her değer türü için, aynı değer kümesinin yanı sıra değerini belirten karşılık gelen bir null atanabilir değer nulltürü vardır.

Değer türündeki bir değişkene atama, atanmakta olan değerin bir kopyasını oluşturur. Bu, başvuru türündeki bir değişkene atamadan farklıdır ve başvuru tarafından tanımlanan nesneyi kopyalar ancak kopyalanmaz.

8.3.2 System.ValueType türü

Tüm değer türleri örtük olarak sınıfından classSystem.ValueTypedevralır object. Herhangi bir türün bir değer türünden türetmesi mümkün değildir ve bu nedenle değer türleri örtük olarak mühürlenir (§15.2.2.3).

System.ValueType Bunun kendisi bir value_type olmadığını unutmayın. Bunun yerine, tüm value_type otomatik olarak türetildiği bir class_type.

8.3.3 Varsayılan oluşturucular

Tüm değer türleri, varsayılan oluşturucu olarak adlandırılan bir genel parametresiz örnek oluşturucuyu örtük olarak bildirir. Varsayılan oluşturucu, değer türü için varsayılan değer olarak bilinen sıfırdan başlatılan bir örnek döndürür:

  • Tüm simple_typeiçin varsayılan değer, tüm sıfırların bit deseni tarafından üretilen değerdir:
    • sbyte, , byte, short, ushort, int, uint, longve ulongiçin varsayılan değerdir0.
    • için charvarsayılan değer şeklindedir '\x0000'.
    • için floatvarsayılan değer şeklindedir 0.0f.
    • için doublevarsayılan değer şeklindedir 0.0d.
    • için decimalvarsayılan değerdir 0m (yani, 0 ölçeğindeki sıfır değeridir).
    • için boolvarsayılan değer şeklindedir false.
    • E için varsayılan değer türüne 0Edönüştürülür.
  • bir struct_type için varsayılan değer, tüm değer türü alanlarını varsayılan değerlerine ve tüm başvuru türü alanlarını nulldeğerine ayarlayarak üretilen değerdir.
  • Bir nullable_value_type için varsayılan değer, özelliğinin HasValue false olduğu bir örnektir. Varsayılan değer, null atanabilir değer türünün null değeri olarak da bilinir. Böyle bir değerin Value özelliğinin okunmaya çalışılması, tür System.InvalidOperationException özel durumunun (§8.3.12) olmasına neden olur.

Diğer tüm örnek oluşturucular gibi, bir değer türünün varsayılan oluşturucusunun işleci kullanılarak çağrılır new .

Not: Verimlilik nedenleriyle, bu gereksinim aslında uygulamanın bir oluşturucu çağrısı oluşturmasını sağlamak için tasarlanmamıştır. Değer türleri için, varsayılan değer ifadesi (§12.8.21) varsayılan oluşturucuyu kullanarak aynı sonucu verir. son not

Örnek: Aşağıdaki kodda, i ve j değişkenleri ksıfır olarak başlatılır.

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

son örnek

Her değer türünün örtük olarak bir ortak parametresiz örnek oluşturucusunun olması nedeniyle, yapı türünün parametresiz oluşturucunun açık bir bildirimini içermesi mümkün değildir. Ancak yapı türünün parametreli örnek oluşturucuları (§16.4.9) bildirmesine izin verilir.

8.3.4 Yapı türleri

Yapı türü, sabitleri, alanları, yöntemleri, özellikleri, olayları, dizin oluşturucuları, işleçleri, örnek oluşturucularını, statik oluşturucuları ve iç içe yerleştirilmiş türleri bildirebilen bir değer türüdür. Yapı türlerinin bildirimi §16'da açıklanmıştır.

8.3.5 Basit türler

C# basit türler olarak adlandırılan önceden tanımlanmış struct türler kümesi sağlar. Basit türler anahtar sözcükler aracılığıyla tanımlanır, ancak bu anahtar sözcükler, aşağıdaki tabloda açıklandığı gibi ad alanında struct önceden tanımlanmış System türler için yalnızca diğer adlardır.

Anahtar sözcük Diğer ad türü
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 yapı türüne diğer ad verdiği için, her basit türün üyeleri vardır.

Örnek: int içinde bildirilen System.Int32 üyeleri ve üyelerin öğesinden System.Objectdevralınır ve aşağıdaki deyimlere izin verilir:

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

son örnek

Not: Basit türler, bazı ek işlemlere izin verdikleri için içindeki diğer yapı türlerinden farklıdır:

  • Çoğu basit tür, değerlerin değişmez değerler (§6.4.5) yazılarak oluşturulmasına izin verir, ancak C# genel olarak yapı türlerinin değişmez değerleri için sağlama yapmaz. Örnek: 123 türün int değişmez değeridir ve 'a' türünün chardeğişmez değeridir. son örnek
  • bir ifadenin işlenenlerinin tümü basit tür sabitleri olduğunda, derleyicinin derleme zamanında ifadeyi değerlendirmesi mümkündür. Böyle bir ifade constant_expression (§12.23) olarak bilinir. Diğer yapı türleri tarafından tanımlanan işleçleri içeren ifadeler sabit ifadeler olarak kabul edilmez
  • Bildirimler aracılığıyla const , basit türlerin sabitlerini bildirmek mümkündür (§15.4). Diğer yapı türlerinin sabitlerine sahip olmak mümkün değildir, ancak benzer bir etki statik salt okunur alanlar tarafından sağlanır.
  • Basit türleri içeren dönüştürmeler, diğer yapı türleri tarafından tanımlanan dönüştürme işleçlerinin değerlendirilmesine katılabilir, ancak kullanıcı tanımlı dönüştürme işleci hiçbir zaman başka bir kullanıcı tanımlı dönüştürme işlecinin (§10.5.3) değerlendirmesine katılamıyor.

bitiş notunu seçin.

8.3.6 Integral türleri

C# dokuz tam sayı türünü destekler: sbyte, byte, short, ushort, int, , uint, longulongve char. İntegral türleri aşağıdaki değer boyutlarına ve aralıklarına sahiptir:

  • türü sbyte , 'den -128127değerine (dahil) sahip imzalı 8 bitlik tamsayıları temsil eder.
  • türü, byte 'den 0255değerine (dahil) kadar olan işaretsiz 8 bitlik tamsayıları temsil eder.
  • türü, short 'den -3276832767değerine (dahil) sahip imzalı 16 bit tamsayıları temsil eder.
  • türü, ushort 'den 065535değerine (dahil) kadar olan işaretsiz 16 bit tamsayıları temsil eder.
  • türü, int 'den -21474836482147483647değerine (dahil) sahip imzalı 32 bit tamsayıları temsil eder.
  • türü uint , 'den 04294967295değerine (dahil) kadar olan işaretsiz 32 bit tamsayıları temsil eder.
  • türü, long 'den -92233720368547758089223372036854775807değerine (dahil) sahip imzalı 64 bit tamsayıları temsil eder.
  • türü, ulong 'den 018446744073709551615değerine (dahil) sahip işaretsiz 64 bit tamsayıları temsil eder.
  • türü, char 'den 065535değerine (dahil) kadar olan işaretsiz 16 bit tamsayıları temsil eder. Türü için olası değerler char kümesi Unicode karakter kümesine karşılık gelir.

    Not: ile aynı gösterime charsahip olsa daushort, bir tür üzerinde izin verilen tüm işlemlere diğerinde izin verilmez. son not

tüm imzalı integral türleri, ikinin tamamlayıcı biçimi kullanılarak temsil edilir.

integral_type birli ve ikili işleçler her zaman §12.4.7'de ayrıntılı olarak açıklandığı gibi imzalı 32 bit duyarlık, imzasız 32 bit duyarlık, imzalı 64 bit duyarlık veya işaretsiz 64 bit duyarlık ile çalışır.

Türü char bir integral türü olarak sınıflandırılır, ancak iki şekilde diğer integral türlerinden farklıdır:

  • Diğer türlerden türe char önceden tanımlanmış örtük dönüştürme yoktur. Özellikle, ve byte türleri türü kullanılarak ushort tam olarak temsil edilebilir değer aralıklarına sahip olsa char da, sbayt, bayttan örtük dönüştürmeler veya ushortchar mevcut değildir.
  • Türün char sabitleri character_literals veya integer_literals olarak yazı tipi karakteri ile birlikte yazılmalıdır.

Örnek: (char)10 ile '\x000A'aynıdır. son örnek

checked ve unchecked işleçleri ve deyimleri, tamsayı türü aritmetik işlemler ve dönüştürmeler (§12.8.20) için taşma denetimini denetlemek için kullanılır. Bir checked bağlamda, taşma bir derleme zamanı hatası oluşturur veya bir System.OverflowException oluşturulmasına neden olur. Bağlamda unchecked taşmalar yoksayılır ve hedef türe sığmayan yüksek sıralı bitler atılır.

8.3.7 Kayan nokta türleri

C# iki kayan nokta türünü destekler: float ve double. float ve double türleri, aşağıdaki değer kümelerini sağlayan 32 bit tek duyarlıklı ve 64 bit çift duyarlıklı IEC 60559 biçimleri kullanılarak temsil edilir:

  • Pozitif sıfır ve negatif sıfır. Çoğu durumda pozitif sıfır ve negatif sıfır, basit sıfır değeriyle aynı şekilde davranır, ancak bazı işlemler ikisi arasında ayrım (§12.10.3) gerçekleştirir.
  • Pozitif sonsuzluk ve negatif sonsuzluk. Sonsuzlar, sıfır olmayan bir sayıyı sıfıra bölme gibi işlemler tarafından üretilir.

    Örnek: 1.0 / 0.0 pozitif sonsuzluk verir ve –1.0 / 0.0 negatif sonsuzluk verir. son örnek

  • Sayı Olmayan değeri, genellikle NaN olarak kısaltılır. NaN'ler, sıfırı sıfıra bölme gibi geçersiz kayan nokta işlemleriyle oluşturulur.
  • Formun sıfır olmayan değerlerinin sonlu kümesi × m × 2e, burada s 1 veya −1, m ve e ise belirli kayan nokta türüne göre belirlenir: için, 0< 2²⁴ ve −149 ≤ < ≤ 104 ve için, 0 double< 2⁵³ ve −1075 ≤ < ≤ 970. Normalleştirilmiş kayan noktalı sayılar geçerli sıfır olmayan değerler olarak kabul edilir. C# uyumlu bir uygulamanın normalleştirilmiş kayan nokta sayılarını desteklemesini gerektirmez veya yasaklamaz.

Bu float tür, yaklaşık 1,5 × 10⁻⁴⁵ ile 3,4 × 10³⁸ arasındaki değerleri 7 basamaklı duyarlıkla temsil edebilir.

Bu double tür, yaklaşık 5,0 × 10⁻³²⁴ ile 1,7 × 10³⁰⁸ arasında 15-16 basamaklı bir duyarlıkla değerleri temsil edebilir.

İkili işlecin işlenenlerinden biri kayan nokta türündeyse, §12.4.7'de ayrıntılı olarak açıklandığı gibi standart sayısal yükseltmeler uygulanır ve işlem veya float duyarlıkla double gerçekleştirilir.

Atama işleçleri de dahil olmak üzere kayan nokta işleçleri hiçbir zaman özel durum oluşturmaz. Bunun yerine, olağanüstü durumlarda kayan nokta işlemleri aşağıda açıklandığı gibi sıfır, sonsuz veya NaN üretir:

  • Kayan nokta işleminin sonucu, hedef biçimde en yakın temsil edilebilir değere yuvarlanir.
  • Kayan nokta işleminin sonucunun büyüklüğü hedef biçim için çok küçükse, işlemin sonucu pozitif sıfır veya negatif sıfır olur.
  • Kayan nokta işleminin sonucunun büyüklüğü hedef biçim için çok büyükse, işlemin sonucu pozitif sonsuz veya negatif sonsuz olur.
  • Kayan nokta işlemi geçersizse, işlemin sonucu NaN olur.
  • Kayan nokta işleminin işlenenlerinden biri veya her ikisi de NaN ise, işlemin sonucu NaN olur.

Kayan nokta işlemleri, işlemin sonuç türünden daha yüksek hassasiyetle gerçekleştirilebilir. Kayan nokta türündeki bir değeri türünün tam duyarlığıyla zorlamak için açık bir atama (§12.9.7) kullanılabilir.

Örnek: Bazı donanım mimarileri, türünden daha büyük aralık ve duyarlık ile "genişletilmiş" veya "uzun çift" kayan double nokta türünü destekler ve bu daha yüksek duyarlık türünü kullanarak tüm kayan nokta işlemlerini örtük olarak gerçekleştirir. Yalnızca performans açısından aşırı maliyetle bu tür donanım mimarileri daha az duyarlıkla kayan nokta işlemleri gerçekleştirmek için yapılabilir ve hem performans hem de duyarlık kaybı için bir uygulama gerektirmek yerine, C# tüm kayan nokta işlemleri için daha yüksek bir duyarlık türü kullanılmasına izin verir. Daha kesin sonuçlar sunmanın dışında, bu nadiren ölçülebilir etkilere sahiptir. Ancak, çarpımın aralığın dışında x * y / z bir sonuç ürettiği, ancak sonraki bölmenin geçici sonucu aralığa geri double getirdiği form doubleifadelerinde, ifadenin daha yüksek aralık biçiminde değerlendirildiği gerçeği sonsuzluk yerine sonlu bir sonucun üretilmesine neden olabilir. son örnek

8.3.8 Ondalık türü

Tür decimal , finansal ve parasal hesaplamalar için uygun olan 128 bitlik bir veri türüdür. Tür, decimal en az -7,9 × 10⁻²⁸ ile 7,9 × 10²⁸ aralığındaki değerleri en az 28 basamaklı duyarlıkla temsil edebilir.

Türün decimal sonlu değer kümesi(–1)v × c × 10⁻e biçimindedir, burada v işareti 0 veya 1, katsayı c 0 ≤ c<Cmax tarafından verilir ve ölçek e, Emin ≤ eEmax şeklindedir; burada Cmax en az 1 × 10²⁸, Emin ≤ 0, ve Emax ≥ 28. Türün decimal imzalı sıfırları, sonsuzlukları veya NaN'leri desteklemesi şart değildir.

A decimal , on üssüyle ölçeklendirilmiş bir tamsayı olarak temsil edilir. decimaldeğerinden küçük 1.0mmutlak değere sahip s için, değer en az 28. ondalık basamayı tam olarak gösterir. decimaldeğerinden büyük veya buna eşit mutlak değere 1.0msahip s için değer en az 28 basamağı tam olarak belirtir. ve float veri türlerinin double aksine, gibi 0.1 ondalık kesirli sayılar tam olarak ondalık gösterimde gösterilebilir. float ve double gösterimlerinde, bu tür sayılar genellikle sonlandırıcı olmayan ikili genişletmelere sahiptir ve bu da bu gösterimleri yuvarlama hatalarına daha açık hale getirir.

İkili işlecin decimal işlenenlerinden biri türündeyse, §12.4.7'de ayrıntılı olarak açıklandığı gibi standart sayısal yükseltmeler uygulanır ve işlem duyarlıkla double gerçekleştirilir.

Tür decimal değerleri üzerindeki bir işlemin sonucu, tam sonucun hesaplanmasından (her işleç için tanımlandığı gibi ölçeğin korunması) ve ardından gösterimi sığdırmak için yuvarlamanın sonucudur. Sonuçlar en yakın temsil edilebilir değere yuvarlanıp, bir sonuç iki temsil edilebilir değere eşit olarak yakın olduğunda, en az önemli basamak konumunda çift sayıya sahip olan değere (bu "bankacı yuvarlama" olarak bilinir) yuvarlanir. Yani, sonuçlar en az 28. ondalık basamayı gösterir. Yuvarlamanın sıfır olmayan bir değerden sıfır değeri üretebileceğini unutmayın.

Aritmetik bir decimal işlem, büyüklüğü biçim için decimal çok büyük olan bir sonuç üretirse, bir System.OverflowException oluşturulur.

Türün decimal duyarlığı daha yüksektir, ancak kayan nokta türlerinden daha küçük bir aralığa sahip olabilir. Bu nedenle, kayan nokta türlerinden 'a decimal dönüştürmeler taşma özel durumları üretebilir ve kayan decimal nokta türlerine dönüştürmeler duyarlık veya taşma özel durumlarının kaybına neden olabilir. Bu nedenlerden dolayı, kayan nokta türleri ile decimalarasında örtük dönüştürme yoktur ve açık atamalar olmadan, kayan nokta ve decimal işlenenler aynı ifadede doğrudan karıştırıldığında derleme zamanı hatası oluşur.

8.3.9 Bool türü

türü Boole bool mantıksal miktarlarını temsil eder. Türün bool olası değerleri ve trueşeklindedirfalse. temsili false §8.3.3'te açıklanmıştır. gösterimi true belirtilmemiş olsa da, ile aynısından farklı falseolacaktır.

ve diğer değer türleri arasında bool standart dönüştürme yoktur. Özellikle, bool tür ayrıdır ve integral türlerinden ayrıdır, tamser değer yerine bir bool değer kullanılamaz ve tam tersi de geçerlidir.

Not: C ve C++ dillerinde sıfır integral veya kayan nokta değeri ya da null işaretçi Boole değerine false, sıfır olmayan integral veya kayan nokta değerine dönüştürülebilir ya da null olmayan bir işaretçi Boole değerine truedönüştürülebilir. C# dilinde bu tür dönüştürmeler, bir integral veya kayan nokta değerini açıkça sıfırla karşılaştırarak veya nesne başvurusu nullaçıkça ile karşılaştırılarak gerçekleştirilir. son not

8.3.10 Numaralandırma türleri

Numaralandırma türü, adlandırılmış sabitleri olan ayrı bir türdür. Her sabit listesi türü, , byte, , sbyteshort, ushort, intuint veya longolacak ulongtemel bir türe sahiptir. Numaralandırma türünün değer kümesi, temel alınan türün değer kümesiyle aynıdır. Numaralandırma türünün değerleri adlandırılmış sabitlerin değerleriyle sınırlı değildir. Numaralandırma türleri, numaralandırma bildirimleri (§19.2) aracılığıyla tanımlanır.

8.3.11 Tanımlama Grubu türleri

Tanımlama grubu türü, isteğe bağlı adlara ve tek tek türlere sahip sıralı, sabit uzunlukta bir değer dizisini temsil eder. Bir tanımlama grubu türündeki öğelerin sayısı, onun arity değeri olarak adlandırılır. Tanımlama grubu türü n ≥ 2 ile yazılır (T1 I1, ..., Tn In) ve burada tanımlayıcılar I1...In isteğe bağlı tanımlama grubu öğe adlarıdır.

Bu söz dizimi, türü ile yapılandırılmış bir türün T1...TnSystem.ValueTuple<...>kısaltmasıdır. Bu, iki ile yedi arasında (dahil) herhangi bir demet türünü doğrudan ifade edebilen bir dizi genel yapı türü olacaktır. Herhangi bir System.ValueTuple<...> tanımlama grubu türünün arlığına karşılık gelen sayıda tür parametresiyle doğrudan eşleşen bir bildirim olması gerekmez. Bunun yerine, değeri yediden büyük olan demetler, tanımlama grubu öğelerine ek olarak, başka System.ValueTuple<T1, ..., T7, TRest> bir tür Rest kullanılarak kalan öğelerin iç içe değerini içeren bir System.ValueTuple<...> alana sahip olan genel bir yapı türüyle temsil edilir. Bu tür iç içe yerleştirme, örneğin bir Rest alanın varlığı yoluyla çeşitli şekillerde gözlemlenebilir. Yalnızca tek bir ek alanın gerekli olduğu durumlarda genel yapı türü System.ValueTuple<T1> kullanılır; bu tür kendi içinde bir tanımlama grubu türü olarak kabul edilmez. Yediden fazla ek alanın gerekli olduğu durumlarda özyinelemeli System.ValueTuple<T1, ..., T7, TRest> olarak kullanılır.

Bir tanımlama grubu türü içindeki öğe adları ayrı olmalıdır. formunItemXX, bir tanımlama grubu öğesinin konumunu temsil edebilen başlatılmamış ondalık basamaklardan oluşan0 herhangi bir dizi olduğu bir tanımlama grubu öğesi adı, yalnızca tarafından Xbelirtilen konumda izin verilir.

İsteğe bağlı öğe adları türlerde ValueTuple<...> gösterilmez ve tanımlama grubu değerinin çalışma zamanı gösteriminde depolanmaz. Kimlik dönüştürmeleri (§10.2.2) öğe türlerinin kimlik dönüştürülebilir dizilerine sahip tanımlama kümeleri arasında bulunur.

new§12.8.17.2 işleci tanımlama grubu türü söz dizimi new (T1, ..., Tn)ile uygulanamaz. Tanımlama grubu değerleri tanımlama grubu ifadelerinden (§12.8.6) veya işleci doğrudan öğesinden newoluşturulan bir türe uygulanarak ValueTuple<...> oluşturulabilir.

Tanımlama grubu öğeleri, , Item1vb. adlarına Item2sahip genel alanlardır ve bir tanımlama grubu değeri (§12.8.7) üzerindeki üye erişimi aracılığıyla erişilebilir. Ayrıca, tanımlama grubu türünün belirli bir öğe için bir adı varsa, söz konusu öğeye erişmek için bu ad kullanılabilir.

Not: Büyük tanımlama grupları iç içe System.ValueTuple<...> değerlerle temsil edilse bile, her tanımlama grubu öğesine konumuna Item... karşılık gelen adla doğrudan erişilebilir. son not

Örnek: Aşağıdaki örnekler verilmiştir:

(int, string) pair1 = (1, "One");
(int, string word) pair2 = (2, "Two");
(int number, string word) pair3 = (3, "Three");
(int Item1, string Item2) pair4 = (4, "Four");
// Error: "Item" names do not match their position
(int Item2, string Item123) pair5 = (5, "Five");
(int, string) pair6 = new ValueTuple<int, string>(6, "Six");
ValueTuple<int, string> pair7 = (7, "Seven");
Console.WriteLine($"{pair2.Item1}, {pair2.Item2}, {pair2.word}");

, pair1ve pair2 için tanımlama grubu türleripair3, tanımlama grubu türü öğelerinin bazıları veya tümü için adlarla birlikte geçerlidir.

Adların pair4 ve konumlarının eşleşmesi nedeniyle için tanımlama grubu türü Item1 geçerlidir, ancak adlar Item2 ve pair5Item2 eşleşmediğinden için tanımlama grubu türüne Item123 izin verilmez.

ve pair6 bildirimleripair7, tanımlama grubu türlerinin formun ValueTuple<...>oluşturulmuş türleriyle değiştirilebilir olduğunu ve işlecine new ikinci söz dizimiyle izin verildiğini gösterir.

Son satır, tanımlama grubu öğelerine hem konumlarına karşılık gelen adla hem de türünde varsa ilgili tanımlama grubu öğesi adına göre erişilebileceğini Item gösterir. son örnek

8.3.12 Null değer türleri

Null atanabilir bir değer türü, temel alınan türün tüm değerlerini ve ek bir null değeri temsil edebilir. Null atanabilir bir değer türü yazılır T?; burada T temel alınan türdür. Bu söz dizimi için System.Nullable<T>kısaltmadır ve iki form birbirinin yerine kullanılabilir.

Buna karşılık, boş değer atanamayan bir değer türü, ve kısaltması System.Nullable<T>T? (herhangi biri Tiçin) dışında herhangi bir değer türü, ayrıca null değer türü olmayan bir değer türü (yani değer türü kısıtlaması olan herhangi bir tür parametresi (§15.2.5)) olarak kısıtlanan herhangi bir tür parametresidir. türü System.Nullable<T> için Tdeğer türü kısıtlamasını belirtir. Bu, null atanabilir bir değer türünün temel alınan türünün boş değer atanamayan herhangi bir değer türü olabileceği anlamına gelir. Null atanabilir bir değer türünün temel türü, null atanabilir bir değer türü veya başvuru türü olamaz. Örneğin, int?? geçersiz bir türdür. Null atanabilir başvuru türleri §8.9 kapsamındadır.

Null atanabilir bir değer türünün T? örneği iki genel salt okunur özelliğe sahiptir:

  • HasValue Türün özelliğibool
  • Value Türün özelliğiT

Örneğin HasValuetrue null olmayan olduğu söylenir. Null olmayan bir örnek bilinen bir değer içerir ve Value bu değeri döndürür.

örneğinin HasValuefalse null olduğu söylenir. Null örnek tanımlanmamış bir değere sahiptir. Null örneğinin Value okunmaya çalışılması, bir System.InvalidOperationException atılması neden olur. Null atanabilir bir örneğin Value özelliğine erişme işlemi, unwrapping olarak adlandırılır.

Varsayılan oluşturucuya ek olarak, her null atanabilir değer türünün T? türünde Ttek bir parametresi olan bir ortak oluşturucu vardır. türünde xbir değer T verilip formun oluşturucu çağrısı

new T?(x)

, özelliğinin T? olduğu Valuenull olmayan bir örneğini x oluşturur. Belirli bir değer için null değer türünün null olmayan bir örneğini oluşturma işlemi sarmalama olarak adlandırılır.

Örtük dönüştürmeler değişmez değerden (§10.2.7TT?

Null atanabilir değer türü T? arabirim uygulamaz (§18). Özellikle bu, temel alınan türün T uyguladığı hiçbir arabirimi uygulamadığı anlamına gelir.

8.3.13 Kutulama ve kutu açma

Kutulama ve kutu açma kavramı, bir value_typeobjectköprü sağlar. Kutulama ve kutu açma, herhangi bir türdeki bir değerin sonunda olarak işlenebileceği tür sisteminin birleşik bir objectgörünümünü etkinleştirir.

Boks , §10.2.9'da daha ayrıntılı olarak açıklanmıştır ve kutu açma özelliği ise §10.3.7'de açıklanmıştır.

8.4 Yapılı türler

8.4.1 Genel

Genel tür bildirimi, tür bağımsız değişkenlerini uygulayarak birçok farklı tür oluşturmak için "şema" olarak kullanılan ilişkisiz bir genel türü tek başına belirtir. Tür bağımsız değişkenleri, genel türün adının hemen ardından açılı ayraçlar (< ve >) içinde yazılır. En az bir tür bağımsız değişkeni içeren bir tür, yapılı tür olarak adlandırılır. Yapıtlı tür, dildeki bir tür adının görüntülenebildiği çoğu yerde kullanılabilir. İlişkisiz genel tür yalnızca bir typeof_expression içinde kullanılabilir (§12.8.18).

Yapılandırılmış türler, ifadelerde basit adlar (§12.8.4) veya üyeye erişirken (§12.8.7) de kullanılabilir.

Bir namespace_or_type_name değerlendirildiğinde, yalnızca doğru tür parametresi sayısına sahip genel türler dikkate alınır. Bu nedenle, türlerde farklı sayıda tür parametresi olduğu sürece, farklı türleri tanımlamak için aynı tanımlayıcıyı kullanmak mümkündür. Bu, aynı programdaki genel ve genel olmayan sınıfları karıştırırken kullanışlıdır.

Örnek:

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
    }
}

son örnek

namespace_or_type_name üretimlerinde ad araması için ayrıntılı kurallar §7.8'de açıklanmıştır. Bu üretimlerdeki belirsizliklerin çözümü §6.2.5'te açıklanmıştır. Bir type_name , tür parametrelerini doğrudan belirtmese bile, yapılı bir türü tanımlayabilir. Bu durum, bir türün genel class bir bildirimin içinde iç içe geçtiği ve içeren bildirimin örnek türünün ad araması (§15.3.9.7) için örtük olarak kullanıldığı durumlarda oluşabilir.

Örnek:

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

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

son örnek

Sabit listesi olmayan bir tür unmanaged_type (§8.8) olarak kullanılmamalıdır.

8.4.2 Tür bağımsız değişkenleri

Tür bağımsız değişken listesindeki her bağımsız değişken yalnızca bir türdür.

type_argument_list
    : '<' type_arguments '>'
    ;

type_arguments
    : type_argument (',' type_argument)*
    ;   

type_argument
    : type
    | type_parameter nullable_type_annotation?
    ;

Her tür bağımsız değişkeni, ilgili tür parametresindeki (§15.2.5) kısıtlamaları karşılar. Null atanabilirliği tür parametresinin null atanabilirliğiyle eşleşmeyen bir başvuru türü bağımsız değişkeni kısıtlamayı karşılar; ancak bir uyarı verilebilir.

8.4.3 Açık ve kapalı türler

Tüm türler açık türler veya kapalı türler olarak sınıflandırılabilir. Açık tür, tür parametrelerini içeren bir türdür. Daha açık belirtmek gerekirse:

  • Tür parametresi açık bir tür tanımlar.
  • Dizi türü, yalnızca öğe türü açık bir türse açık bir türdür.
  • Yalnızca türü bağımsız değişkenlerinden biri veya daha fazlası açık bir türse, yapılı tür açık bir türdür. İç içe yerleştirilmiş bir tür, yalnızca bir veya daha fazla tür bağımsız değişkeni veya içeren türlerin tür bağımsız değişkenleri açık bir türse açık bir türdür.

Kapalı tür, açık bir tür olmayan bir türdür.

Çalışma zamanında, genel tür bildirimi içindeki kodun tümü, 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. Genel türdeki her tür parametresi belirli bir çalışma zamanı türüne bağlıdır. Tüm deyim ve ifadelerin çalışma zamanı işlemesi her zaman kapalı türlerle gerçekleşir ve açık türler yalnızca derleme zamanı işleme sırasında gerçekleşir.

Aynı ilişkisiz genel türden oluşturulurlarsa ve karşılık gelen tür bağımsız değişkenlerinin her biri arasında bir kimlik dönüştürmesi varsa, iki kapalı yapı türü kimlik dönüştürülebilir (§10.2.2) olur. Karşılık gelen tür bağımsız değişkenleri, kimliği dönüştürülebilir olan, kendilerinden ayrılmış türler veya tanımlama kümeleri olabilir. Kimliği dönüştürülebilir olan kapalı yapılı türler tek bir statik değişken kümesini paylaşır. Aksi takdirde, kapatılan her tür kendi statik değişken kümesine sahiptir. Çalışma zamanında açık bir tür olmadığından, açık bir türle ilişkili statik değişken yoktur.

8.4.4 İlişkili ve ilişkisiz türler

İlişkisiz tür terimi genel olmayan bir türe veya ilişkisiz genel türe başvurur. İlişkili tür terimi genel olmayan bir türe veya bir yapı türüne başvurur.

İlişkisiz bir tür, tür bildirimi tarafından bildirilen varlığa başvurur. İlişkisiz genel tür kendisi bir tür değildir ve değişken türü, bağımsız değişken veya dönüş değeri olarak ya da temel tür olarak kullanılamaz. İlişkisiz genel türe başvurulabilecek tek yapı ifadedir typeof (§12.8.18).

8.4.5 Kısıtlamaları karşılama

Her yapılandırılmış türe veya genel yönteme başvurulsa, sağlanan tür bağımsız değişkenleri genel tür veya yöntemde (§15.2.5) bildirilen tür parametresi kısıtlamalarına karşı denetlenmektedir. Her where yan tümce için, adlandırılmış tür parametresine karşılık gelen tür bağımsız değişkeni A aşağıdaki gibi her kısıtlamaya karşı denetlenmektedir:

  • Kısıtlama bir class tür, arabirim türü veya tür parametresiyse, kısıtlamada görünen herhangi bir tür parametresinin yerine sağlanan tür bağımsız değişkenleriyle bu kısıtlamayı temsil etmesine izin verin C . Kısıtlamayı karşılamak için, türün A aşağıdakilerden birine göre türe C dönüştürülebilir olması gerekir:
    • Kimlik dönüştürme (§10.2.2)
    • Örtük başvuru dönüştürmesi (§10.2.8)
    • Bir kutulama dönüştürmesi (§10.2.9), bu tür A null atanamaz bir değer türü olması koşuluyla.
    • Bir tür parametresinden öğesine örtük başvuru, kutulama veya tür parametresi ACdönüştürmesi.
  • Kısıtlama başvuru türü kısıtlaması ()class ise, tür A aşağıdakilerden birini karşılamalı:
    • A bir arabirim türü, sınıf türü, temsilci türü, dizi türü veya dinamik türdür.

    Not: System.ValueType ve System.Enum bu kısıtlamayı karşılayan başvuru türleridir. son not

    • A , başvuru türü (§8.2) olarak bilinen bir tür parametresidir.
  • Kısıtlama değer türü kısıtlaması ()struct ise, tür A aşağıdakilerden birini karşılamalı:
    • A bir struct tür veya enum türdür, ancak null atanabilir bir değer türü değildir.

    Not: System.ValueType ve System.Enum bu kısıtlamayı karşılamayan başvuru türleridir. son not

    • A değer türü kısıtlamasını (§15.2.5) içeren bir tür parametresidir.
  • Kısıtlama oluşturucu kısıtlaması new()ise, türü A olmamalıdır abstract ve genel parametresiz bir oluşturucuya sahip olmalıdır. Aşağıdakilerden biri doğruysa bu durum geçerlidir:
    • A bir değer türüdür, çünkü tüm değer türlerinin bir ortak varsayılan oluşturucu (§8.3.3) vardır.
    • A , oluşturucu kısıtlamasını (§15.2.5) içeren bir tür parametresidir.
    • A değer türü kısıtlamasını (§15.2.5) içeren bir tür parametresidir.
    • A class soyut olmayan ve parametresiz açıkça bildirilen bir ortak oluşturucu içerir.
    • A değildir abstract ve varsayılan bir oluşturucuya sahiptir (§15.11.5).

Bir tür parametresinin kısıtlamalarından biri veya daha fazlası verilen tür bağımsız değişkenleri tarafından karşılanmazsa derleme zamanı hatası oluşur.

Tür parametreleri devralınmadığından, kısıtlamalar da hiçbir zaman devralınmaz.

Örnek: Aşağıda, D türü parametresinde TT kısıtlamayı belirterek temel classB<T>tarafından uygulanan kısıtlamayı karşılaması gerekir. Buna karşılık, classE herhangi bir için uygulandığından List<T> kısıtlama IEnumerable belirtmeye gerek yokturT.

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

son örnek

8.5 Tür parametreleri

Tür parametresi, parametrenin çalışma zamanında bağlı olduğu bir değer türünü veya başvuru türünü belirten bir tanımlayıcıdır.

type_parameter
    : identifier
    ;

Bir tür parametresinin örneği birçok farklı tür bağımsız değişkeniyle oluşturulabildiğinden, tür parametreleri diğer türlerden biraz farklı işlemlere ve kısıtlamalara sahiptir.

Not: Bunlar şunlardır:

son not

Tür olarak, tür parametreleri yalnızca bir derleme zamanı yapısıdır. Çalışma zamanında, her tür parametresi, genel tür bildirimine bir tür bağımsız değişkeni sağlayarak belirtilen bir çalışma zamanı türüne bağlıdır. Bu nedenle, tür parametresiyle bildirilen bir değişkenin türü, çalışma zamanında , §8.4.3 kapalı bir tür olarak oluşturulacaktır. Tür parametreleriyle ilgili tüm deyimlerin ve ifadelerin çalışma zamanı yürütmesi, bu parametre için tür bağımsız değişkeni olarak sağlanan türü kullanır.

8.6 İfade ağacı türleri

İfade ağaçları , lambda ifadelerinin yürütülebilir kod yerine veri yapıları olarak temsil edilmesine izin verir. İfade ağaçları, herhangi bir temsilci türü olan formun ifade ağacı türlerinin değerleridir.System.Linq.Expressions.Expression<TDelegate>TDelegate Bu belirtimin geri kalanı için bu türlere kısaltması Expression<TDelegate>kullanılarak başvurulacaktır.

Lambda ifadesinden temsilci türüne Ddönüştürme varsa, ifade ağacı türüne Expression<TDelegate>dönüştürme de vardır. Lambda ifadesinin temsilci türüne dönüştürülmesi lambda ifadesi için yürütülebilir koda başvuran bir temsilci oluştururken, ifade ağacı türüne dönüştürme, lambda ifadesinin ifade ağacı gösterimini oluşturur. Bu dönüştürmenin diğer ayrıntıları §10.7.3'te sağlanmıştır.

Örnek: Aşağıdaki program bir lambda ifadesini hem yürütülebilir kod hem de ifade ağacı olarak temsil eder. dönüştürmesi Func<int,int>olduğundan, için bir dönüştürme de vardır Expression<Func<int,int>>:

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

Bu atamaların ardından temsilci del , döndüren x + 1bir yönteme başvurur ve ifade ağacı exp ifadesi ifadesini açıklayan bir veri yapısına x => x + 1başvurur.

son örnek

Expression<TDelegate>türünde Compilebir temsilci oluşturan bir örnek yöntemi TDelegate sağlar:

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

Bu temsilciyi çağırmak, ifade ağacı tarafından temsil edilen kodun yürütülmesine neden olur. Bu nedenle, yukarıdaki del tanımları dikkate alır ve del2 eşdeğerdir ve aşağıdaki iki deyim aynı etkiye sahip olur:

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

Bu kodu i1 yürüttkten sonra ve i2 her ikisi de değerine 2sahip olur.

tarafından Expression<TDelegate> sağlanan API yüzeyi, yukarıda açıklanan bir Compile yöntem gereksiniminin ötesinde uygulama tanımlıdır.

Not: İfade ağaçları için sağlanan API'nin ayrıntıları uygulama tanımlı olsa da, bir uygulamanın şunları gerçekleştirmesi beklenir:

  • Bir lambda ifadesinden dönüştürmenin sonucu olarak oluşturulan bir ifade ağacının yapısını incelemek ve yanıtlamak için kodu etkinleştirme
  • kullanıcı kodu içinde programlı olarak oluşturulacak ifade ağaçlarını etkinleştirme

son not

8.7 Dinamik tür

Türüdynamic, diğer tüm türler tarafından kullanılan statik bağlamanın aksine , §12.3.2'de ayrıntılı olarak açıklandığı gibi dinamik bağlama kullanır.

Türü dynamic , aşağıdakiler dışında ile özdeş object olarak kabul edilir:

  • Tür dynamic ifadelerindeki işlemler dinamik olarak bağlanabilir (§12.3.3).
  • Her ikisi de adaysa tür çıkarımı (§12.6.3) tercih dynamicobject edilir.
  • dynamic olarak kullanılamaz
    • object_creation_expression türü (§12.8.17.2)
    • class_base (§15.2.4)
    • member_access predefined_type (§12.8.7.1)
    • işlecin işleneni typeof
    • öznitelik bağımsız değişkeni
    • kısıtlama
    • uzantı yöntemi türü
    • struct_interfaces (§16.2.5) veya interface_type_list (§15.2.4.1) içindeki tür bağımsız değişkeninin herhangi bir bölümü.

Bu denklik nedeniyle, aşağıdakiler şunları tutar:

  • Örtük kimlik dönüştürmesi var
    • ve arasında objectdynamic
    • ile değiştirirken dynamic aynı olan, yapılı türler arasında object
    • ile değiştirirken dynamic aynı olan tanımlama grubu türleri arasında object
  • ve 'den object örtük ve açık dönüştürmeler de ve için dynamicgeçerlidir.
  • ile dynamic değiştirilirken object aynı olan imzalar aynı imza olarak kabul edilir.
  • Türü dynamic , çalışma zamanında türünden object ayırt edilemez.
  • Türündeki dynamic bir ifade dinamik ifade olarak adlandırılır.

8.8 Yönetilmeyen türler

unmanaged_type
    : value_type
    | pointer_type     // unsafe code support
    ;

unmanaged_type, ne bir reference_type ne de yönetilmeyen olma zorunluluğu olmayan bir type_parameter olan ve türü unmanaged_typeolmayan örnek alanları içermeyen herhangi bir türdür. Başka bir deyişle, unmanaged_type aşağıdakilerden biridir:

  • sbyte, , byte, , short, ushort, int, , uint, long, ulong, char, floatdoubleveya decimal. bool
  • Herhangi bir enum_type.
  • Kullanıcı tanımlı struct_type, yalnızca unmanaged_typeörnek alanlarını içerir.
  • Yönetilmeyen olarak kısıtlanmış herhangi bir tür parametresi.
  • Herhangi bir pointer_type (§23.3).

8.9 Başvuru Türleri ve null atanabilirlik

8.9.1 Genel

Null atanabilir başvuru türü, null atanamayan başvuru türüne bir nullable_type_annotation (?) eklenerek belirtilir. Boş değer atanamayan başvuru türü ile karşılık gelen null atanabilir türü arasında anlamsal bir fark yoktur; her ikisi de bir nesneye veya nullbaşvurusu olabilir. nullable_type_annotation varlığı veya yokluğu, bir ifadenin null değerlere izin verip vermediğini bildirir. Bir ifade bu amaca göre kullanılmadığında derleyici tanılama sağlayabilir. İfadenin null durumu §8.9.5 içinde tanımlanır. Null atanabilir başvuru türü ve karşılık gelen null atanamaz başvuru türü (§10.2.2) arasında bir kimlik dönüştürmesi vardır.

Başvuru türleri için iki null atanabilirlik biçimi vardır:

  • nullable: null atanabilir-reference-type atanabilir null. Varsayılan null durumu belki-null'tır.
  • null atanamaz: Null atanamayan başvuruya değer null atanmamalıdır. Varsayılan null durumu null değil.

Not: ve R türleriR?, aynı temel tür Rolan ile temsil edilir. Bu temel türün değişkeni bir nesneye başvuru içerebilir veya değeri nullolabilir ve bu değer "başvuru yok" ifadesini gösterir. son not

Null atanabilir başvuru türü ile karşılık gelen null atanamayan başvuru türü arasındaki bozulma ayrımı, derleyicinin tanılama oluşturmasını sağlar. Derleyici , §8.2.1'de tanımlandığı gibi nullable_type_annotation izin vermelidir. Tanılamalar uyarılarla sınırlı olmalıdır. Ne boş değer atanabilir ek açıklamaların varlığı veya yokluğu ne de boş değer atanabilir bağlamın durumu, derleme zamanında oluşturulan tanılama iletilerindeki değişiklikler dışında bir programın derleme süresini veya çalışma zamanı davranışını değiştiremez.

8.9.2 Null değer atanamayan başvuru türleri

Null değer atanamayan başvuru türü, formun Tbaşvuru türüdür; burada T türün adıdır. Null değer atanamayan bir değişkenin varsayılan null durumu null değildir. Null olmayan bir değerin gerekli olduğu durumlarda belki null olan bir ifade kullanıldığında uyarılar oluşturulabilir.

8.9.3 Boş değer atanabilir başvuru türleri

Formun T? başvuru türü (örneğinstring?), null atanabilir bir başvuru türüdür. Null atanabilir bir değişkenin varsayılan null durumu null olabilir. Ek açıklama ? , bu türdeki değişkenlerin null atanabilir olduğunu gösterir. Derleyici, uyarı vermek için bu amaçları tanıyabilir. Boş değer atanabilir ek açıklama bağlamı devre dışı bırakıldığında, bu ek açıklamayı kullanmak bir uyarı oluşturabilir.

8.9.4 Null atanabilir bağlam

8.9.4.1 Genel

Her kaynak kodu satırının boş değer atanabilir bir bağlamı vardır. Boş değer atanabilir bağlam denetimi (§8.9.4.3) ve null atanabilir uyarılar (§8.9.4.4) için ek açıklamalar ve uyarılar bayrakları sırasıyla. Her bayrak etkinleştirilebilir veya devre dışı bırakılabilir. Derleyici, herhangi bir başvuru değişkeninin null durumunu belirlemek için statik akış analizini kullanabilir. Başvuru değişkeninin null durumu (§8.9.5) null değil, belki null veya belki de varsayılan.

Null atanabilir bağlam, null atanabilir yönergeler (§6.5.9) ve/veya kaynak kodun dışındaki uygulamaya özgü bir mekanizma aracılığıyla kaynak kodu içinde belirtilebilir. Her iki yaklaşım da kullanılırsa, null atanabilir yönergeler bir dış mekanizma aracılığıyla yapılan ayarların yerini alır.

Null atanabilir bağlamın varsayılan durumu uygulama tanımlıdır.

Bu belirtim boyunca, boş değer atanabilir yönerge içermeyen veya geçerli null atanabilir bağlam durumuyla ilgili hiçbir deyimi yapılmayan tüm C# kodunun, hem ek açıklamaların hem de uyarıların etkinleştirildiği null atanabilir bir bağlam kullanılarak derlendiği varsayılır.

Not: Her iki bayrağın da devre dışı bırakıldığı null atanabilir bağlam, başvuru türleri için önceki standart davranışla eşleşir. son not

8.9.4.2 Null atanabilir devre dışı bırakma

Hem uyarı hem de ek açıklama bayrakları devre dışı bırakıldığında, null atanabilir bağlam devre dışı bırakılır.

Null atanabilir bağlam devre dışı bırakıldığında:

  • Ek açıklamasız başvuru türünün bir değişkeni ile başlatıldığında veya değeri nullatandığında uyarı oluşturulmaz.
  • Başvuru türündeki bir değişken null değere sahip olduğunda uyarı oluşturulmaz.
  • herhangi bir başvuru türü Tiçin içindeki ek açıklama ?T? bir ileti oluşturur ve türü T? ile Taynıdır.
  • Herhangi bir tür parametresi kısıtlaması where T : C?için içindeki ek açıklama ?C? bir ileti oluşturur ve türü C? ile Caynıdır.
  • Herhangi bir tür parametresi kısıtlaması where T : U?için içindeki ek açıklama ?U? bir ileti oluşturur ve türü U? ile Uaynıdır.
  • Genel kısıtlama class? bir uyarı iletisi oluşturur. tür parametresi bir başvuru türü olmalıdır.

    Not: Bu ileti, "uyarı" yerine "bilgilendirme" olarak nitelenir, bu nedenle bu iletinin ilgisiz olan null atanabilir uyarı ayarının durumuyla karıştırılmaması gerekir. son not

  • Null-forgiving işlecinin ! (§12.8.9) hiçbir etkisi yoktur.

Örnek:

#nullable disable annotations
string? s1 = null;    // Informational message; ? is ignored
string s2 = null;     // OK; null initialization of a reference
s2 = null;            // OK; null assignment to a reference
char c1 = s2[1];      // OK; no warning on dereference of a possible null;
                      //     throws NullReferenceException
c1 = s2![1];          // OK; ! is ignored

son örnek

8.9.4.3 Boş değer atanabilir ek açıklamalar

Uyarı bayrağı devre dışı bırakıldığında ve ek açıklama bayrağı etkinleştirildiğinde, null atanabilir bağlam ek açıklamalardır.

Null atanabilir bağlam ek açıklamalar olduğunda:

  • herhangi bir başvuru türü Tiçin, içindeki ? ek açıklama T? null atanabilir bir tür olduğunu belirtirkenT?, açıklama ek açıklamasız T null atanamaz.
  • Null atanabilirlikle ilgili tanılama uyarısı oluşturulmaz.
  • Null-forgiving işleci ! (§12.8.9), işleneninin analiz edilen null durumunu ve hangi derleme zamanı tanılama uyarılarının üretildiğini değiştirebilir.

Örnek:

#nullable disable warnings
#nullable enable annotations
string? s1 = null;    // OK; ? makes s2 nullable
string s2 = null;     // OK; warnings are disabled
s2 = null;            // OK; warnings are disabled
char c1 = s2[1];      // OK; warnings are disabled; throws NullReferenceException
c1 = s2![1];          // No warnings

son örnek

8.9.4.4 Null atanabilir uyarılar

Uyarı bayrağı etkinleştirildiğinde ve ek açıklama bayrağı devre dışı bırakıldığında, null atanabilir bağlam uyarılardır.

Null atanabilir bağlam uyarılar olduğunda, derleyici aşağıdaki durumlarda tanılama oluşturabilir:

  • Belki null olduğu belirlenen bir başvuru değişkeni başvurulmaz.
  • Null olmayan türde bir başvuru değişkeni, null olabilecek bir ifadeye atanır.
  • ? null atanabilir başvuru türünü not etmek için kullanılır.
  • null-forgiving işleci ! (§12.8.9), işleneninin null durumunu null değil olarak ayarlamak için kullanılır.

Örnek:

#nullable disable annotations
#nullable enable warnings
string? s1 = null;    // OK; ? makes s2 nullable
string s2 = null;     // OK; null-state of s2 is "maybe null"
s2 = null;            // OK; null-state of s2 is "maybe null"
char c1 = s2[1];      // Warning; dereference of a possible null;
                      //          throws NullReferenceException
c1 = s2![1];          // The warning is suppressed

son örnek

8.9.4.5 Null atanabilir etkinleştirme

Hem uyarı bayrağı hem de ek açıklama bayrağı etkinleştirildiğinde, null atanabilir bağlam etkinleştirilir.

Null atanabilir bağlam etkinleştirildiğinde:

  • herhangi bir başvuru türü Tiçin, içindeki ? ek açıklama T? null atanabilir bir tür oluştururkenT?, ek açıklamasız T null atanamaz.
  • Derleyici, herhangi bir başvuru değişkeninin null durumunu belirlemek için statik akış analizini kullanabilir. Null atanabilir uyarılar etkinleştirildiğinde, başvuru değişkeninin null durumu (§8.9.5) null değil, null veya belki de varsayılan ve
  • null-forgiving işleci ! (§12.8.9), işleneninin null durumunu null değil olarak ayarlar.
  • Bir tür parametresinin null durumu, karşılık gelen tür bağımsız değişkeninin null durumu ile eşleşmiyorsa, derleyici uyarı verebilir.

8.9.5 Nullabiliteler ve null durumlar

Derleyicinin statik analiz gerçekleştirmesi veya null atanabilirlikle ilgili tanılama uyarıları oluşturması gerekmez.

Bu alt makalenin geri kalanı koşullu normatiftir.

Tanılama uyarıları oluşturan bir derleyici bu kurallara uygundur.

Her ifadenin üç null durumundanbiri vardır:

  • belki null: İfadenin değeri null olarak değerlendirilebilir.
  • belki de varsayılan: İfadenin değeri, bu tür için varsayılan değer olarak değerlendirilebilir.
  • not null: İfadenin değeri null değil.

İfadenin varsayılan null durumu türüne ve bildirildiğinde ek açıklama bayrağının durumuna göre belirlenir:

  • Null atanabilir başvuru türünün varsayılan null durumu:
    • Bildirimi, ek açıklama bayrağının etkinleştirildiği metinde olduğunda null olabilir.
    • Bildirimi, ek açıklama bayrağının devre dışı bırakıldığı metinde olduğunda null değil.
  • Null değer atanamayan başvuru türünün varsayılan null durumu null değildir.

Not: Tür default(T) durum kısıtlanmamış tür parametreleriyle kullanılır. Null değer atanamayan tür için etki alanında null olmadığından, durum belki de varsayılandır. son not

Boş değer atanamayan bir başvuru türünün değişkeni (§9.2.1) başlatıldığında veya ek açıklama bayrağının etkinleştirildiği metinde bildirildiğinde null olabilecek bir ifadeye atandığında tanılama oluşturulabilir.

Örnek: Bir parametrenin null atanabilir olduğu ve bu değerin null atanamayan bir türe atandığı aşağıdaki yöntemi göz önünde bulundurun:

#nullable enable
public class C
{
    public void M(string? p)
    {
        // Warning: Assignment of maybe null value to non-nullable variable
        string s = p;
    }
}

Derleyici, null olmayabilecek parametrenin null olmaması gereken bir değişkene atandığı bir uyarı verebilir. Parametre, atamadan önce null kontrolüne tabi tutulursa, derleyici bunu null yapılabilirlik durumu çözümlemesinde kullanabilir ve uyarıda bulunmayabilir.

#nullable enable
public class C
{
    public void M(string? p)
    {
        if (p != null)
        {
            string s = p; // No warning
            // Use s
        }
    }
}

son örnek

Derleyici, çözümlemesinin bir parçası olarak değişkenin null durumunu güncelleştirebilir.

Örnek: Derleyici, programınızdaki deyimleri temel alarak durumu güncelleştirmeyi seçebilir:

#nullable enable
public void M(string? p)
{
    int length = p.Length; // Warning: p is maybe null

    string s = p; // No warning. p is not null

    if (s != null)
    {
        int l2 = s.Length; // No warning. s is not null 
    }
    int l3 = s.Length; // Warning. s is maybe null
}

Önceki örnekte, bir derleyici int length = p.Length;deyiminden sonra, p null durumunun null olmadığını karar verebilir. Null olsaydı, bu deyim bir NullReferenceExceptionoluştururdu. Bu, koddan önce if (p == null) throw NullReferenceException(); gelen davranışa benzer, ancak yazılan kod bir uyarı üretebilir ve bunun amacı örtük olarak bir özel durumun oluşturulabileceği konusunda uyarmaktır. son örnek

Yönteminin ilerleyen bölümlerinde kod, null başvuru olmadığını denetler s . null-state değeri s , null işaretli blok kapatıldıktan sonra null olarak değişebilir. Kodun null olabileceği varsayılarak yazılmış olduğu için, derleyici s'ın null olabileceğini çıkarabilir. Genellikle, kod null denetimi içerdiğinde, derleyici değerin null olabileceğini çıkarsayabilir:

Örnek: Aşağıdaki ifadelerin her biri null denetimin bir biçimini içerir. o'ın boş durumu, her bir ifadenin ardından boş değil durumundan belki boş hale gelebilir.

#nullable enable
public void M(string s)
{
    int length = s.Length; // No warning. s is not null

    _ = s == null; // Null check by testing equality. The null state of s is maybe null
    length = s.Length; // Warning, and changes the null state of s to not null

    _ = s?.Length; // The ?. is a null check and changes the null state of s to maybe null
    if (s.Length > 4) // Warning. Changes null state of s to not null
    {
        _ = s?[4]; // ?[] is a null check and changes the null state of s to maybe null
        _ = s.Length; // Warning. s is maybe null
    }
}

Hem otomatik özellik hem de alan benzeri olay bildirimleri, derleyici tarafından oluşturulan bir yedekleme alanını kullanır. Null durum analizi, olay veya özelliğe yapılan atamanın derleyici tarafından oluşturulan bir yedekleme alanına yapılan atama olduğunu çıkarsayabilir.

Örnek: Bir derleyici, otomatik bir özellik veya alan benzeri bir etkinliği yazmanın karşılık gelen derleyici tarafından oluşturulan arka plan alanını yazdığını belirleyebilir. Özelliğin null durumu, yedekleme alanının durumuyla eşleşir.

class Test
{
    public string P
    {
        get;
        set;
    }

    public Test() {} // Warning. "P" not set to a non-null value.

    static void Main()
    {
        var t = new Test();
        int len = t.P.Length; // No warning. Null state is not null.
    }
}

Önceki örnekte, oluşturucu P null olmayan bir değere ayarlamaz ve derleyici bir uyarı verebilir. P özelliğine erişildiğinde uyarı yoktur, çünkü özelliğin türü null atanamaz bir başvuru türüdür. son örnek

Derleyici, bir özelliği (§15.7) durumlu bir değişken olarak veya bağımsız alma ve ayarlama erişimcileri olarak (§15.7.3) işleyebilir.

Örnek: Derleyici bir özelliğe yazmanın özelliği okumanın null durumunu mu değiştireceğini yoksa bir özelliğin okunmasının bu özelliğin null durumunu mu değiştireceğini seçebilir.

class Test
{
    private string? _field;
    public string? DisappearingProperty
    {
        get
        {
               string tmp = _field;
               _field = null;
               return tmp;
        }
        set
        {
             _field = value;
        }
    }

    static void Main()
    {
        var t = new Test();
        if (t.DisappearingProperty != null)
        {
            int len = t.DisappearingProperty.Length; // No warning. A compiler can assume property is stateful
        }
    }
}

Önceki örnekte, için yedekleme alanı DisappearingProperty okunduğunda null olarak ayarlanmıştır. Ancak, derleyici bir özelliği okumanın bu ifadenin null durumunu değiştirmediğini varsayabilir. son örnek

Derleyici, null durumunu null değil olarak ayarlamak için değişken, özellik veya olayı dereferans eden herhangi bir ifade kullanabilir. Null olsaydı, başvuru kaldırma ifadesi bir NullReferenceExceptionoluştururdu:

Örnek:


public class C
{
    private C? child;
   
    public void M()
    {
        _ = child.child.child; // Warning. Dereference possible null value
        var greatGrandChild = child.child.child; // No warning. 
    }
}

son örnek

Koşullu normatif metnin sonu