Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
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. dipnot
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, sadece tür object
olarak görüntülendiklerinde 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 dynamic
türüdür. 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 tartışılır.
Referans türü değeri, türün bir örneğine bir referanstır ve bu da bir 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_expression(§12.8.17.2) kullanılarak oluşturulur.
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.Object
için bir diğer addır.
8.2.4 Dinamik tür
dynamic
türü, object
gibi, herhangi bir nesneye başvurabilir. türündeki dynamic
ifadelere 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ü
string
türü, doğrudan object
sınıfından devralınan mühürlü 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 sabitleri (§6.4.5.6) olarak yazılabilir.
anahtar sözcüğü string
, önceden tanımlanmış sınıfı System.String
iç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
Bir delege, 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 başvuru depolamakla kalmaz, aynı zamanda yöntemin çağrılacağı nesne örneğine de başvuru depolar. dipnot
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ü değişkenlerine kıyasla, değer türündeki bir değişken, yalnızca değer türü null atanabilir ise null
içerebilir (§8.3.12). 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 null
tü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; çünkü burada başvuru kopyalanır, ancak başvuru tarafından tanımlanan nesne kopyalanmaz.
8.3.2 System.ValueType türü
Tüm değer türleri, örtük olarak class
System.ValueType
sınıfından devralır ve bu da sınıf object
'den devralınır. 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. Tüm value_type değerlerinin otomatik olarak türetildiği bir class_typetir.
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
,long
veulong
için varsayılan değerdir0
. - için
char
varsayılan değer şeklindedir'\x0000'
. - için
float
varsayılan değer şeklindedir0.0f
. - için
double
varsayılan değer şeklindedir0.0d
. - için
decimal
varsayılan değerdir0m
(yani, 0 ölçeğindeki sıfır değeridir). - için
bool
varsayılan değer şeklindedirfalse
. -
enum_type
E
için varsayılan değer0
olupE
türüne dö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ı
null
değ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ğerinValue
özelliğinin okunmaya çalışılması, türSystem.InvalidOperationException
özeldurumunun atılmasına (§8.3.12) neden olur.
Diğer tüm örnek oluşturucular gibi, bir değer türünün varsayılan oluşturucusu new
işleci kullanılarak çağrılır.
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. dipnot
Örnek: Aşağıdaki kodda,
i
vej
değişkenlerik
sı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ürleri kümesi sağlar. Basit türler anahtar sözcükler aracılığıyla tanımlanır, ancak bu anahtar sözcükler yalnızca aşağıdaki tabloda açıklandığı gibi struct
ad alanında önceden tanımlanmış System
türleri için diğer adlardır.
Anahtar Sözcük | Adlandırılmış 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 |
Bir basit tür bir yapı türüne diğer ad verdiğinden, her basit türün üyeleri bulunur.
Örnek:
int
içinde bildirilenSystem.Int32
üyeleri veSystem.Object
'den devralınan üyeleri içerir 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 literal olarak (§6.4.5) yazılarak oluşturulmasına izin verir, ancak C# genel olarak struct türlerinin literal değerleri için bir sağlamlık sağlamaz. Örnek:
123
birint
türünün değişmez değeridir ve'a'
birchar
türünün değ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
, long
ulong
ve char
. İntegral türleri aşağıdaki değer boyutlarına ve aralıklarına sahiptir:
-
sbyte
türü,-128
'den127
'ye kadar olan değerleri (dahil) kapsayan imzalı 8 bitlik tamsayıları temsil eder. - türü,
byte
'den0
255
değerine (dahil) kadar olan işaretsiz 8 bitlik tamsayıları temsil eder. -
short
türü,-32768
ile32767
değerleri arasında (dahil) imzalı 16 bit tamsayıları temsil eder. - türü,
ushort
'den0
65535
değerine (dahil) kadar olan işaretsiz 16 bit tamsayıları temsil eder. -
int
türü,-2147483648
ile2147483647
(dahil) arasında değerlere sahip imzalı 32 bit tamsayıları temsil eder. -
uint
türü,0
'den4294967295
değerine kadar olan (dahil) işaretsiz 32-bit tamsayıları temsil eder. -
long
türü,-9223372036854775808
ile9223372036854775807
aralığındaki, kapsayan, imzalı 64 bit tamsayıları temsil eder. -
ulong
türü,0
ile18446744073709551615
arasındaki değerler dahil olmak üzere işaretsiz 64 bit tamsayıları temsil eder. - türü,
char
'den0
65535
değerine (dahil) kadar olan işaretsiz 16 bit tamsayıları temsil eder. Türü için olası değerlerchar
kümesi Unicode karakter kümesine karşılık gelir.Not:
char
ile aynı gösterime sahip olmasına rağmen, bir tür üzerinde izin verilen tüm işlemler diğerinde izin verilmez. dipnot
tüm imzalı integral türleri, ikinin tamamlayıcı biçimi kullanılarak temsil edilir.
birli ve ikili integral_type işleçleri 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
char
türüne önceden tanımlanmış örtük dönüşümler yoktur. Özellikle,byte
veushort
türlerichar
türünü kullanarak tamamen temsil edilebilir değer aralıklarına sahip olsa da, sbayt, bayt veyaushort
türlerindenchar
türüne örtük dönüşümler mevcut değildir. - Türün
char
sabitleri, karakter türüne dönüştürme ile birlikte character_literals veya integer_literal olarak 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ı meydana getirir veya bir System.OverflowException
oluşturulmasına yol açar. Bağlamda unchecked
taşmalar yoksayılır ve hedef türe sığmayan üst sıradaki 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ğerlerin 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
float
, 0 <m< 2²⁴ ve −149 ≤ e ≤ 104 ve içindouble
, 0 <m< 2⁵³ ve −1075 ≤ e ≤ 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ışındax * y / z
bir sonuç ürettiği, ancak sonraki bölmenin geçici sonucu aralığa geridouble
getirdiği formdouble
ifadelerinde, 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 ≤ e ≤ Emax şeklindedir; burada Cmax en az 1 × 10²⁸, Emin ≤ 0, ve Emax ≥ 28. Türün decimal
imzalı sıfırları, sonsuzlukları veya NaN değerlerini desteklemesi gerekmez.
Bir decimal
, 10'un bir kuvvetiyle ölçeklendirilmiş bir tamsayı olarak temsil edilir.
decimal
değerinden küçük 1.0m
mutlak değere sahip s için, değer en az 28. ondalık basamayı tam olarak gösterir. Mutlak değeri decimal
dan büyük veya eşit olan 1.0m
ler için, değer en az 28 basamak hassasiyetle doğrudur.
float
ve double
veri türlerinin aksine, 0.1
gibi ondalık kesirli sayılar tam olarak ondalık gösterimde temsil edilebilir.
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 bir işlecin işlenenlerinden herhangi biri decimal
türünde ise, §12.4.7'de ayrıntılı olarak açıklandığı gibi standart sayısal yükseltmeler uygulanır ve işlem double
hassasiyetiyle 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 edilebilen değere yuvarlanır ve bir sonuç iki temsil edilebilen değere eşit derecede yakınsa, en az anlamlı basamak konumunda çift sayıya sahip olan değere (ki bu "bankacı yuvarlaması" olarak bilinir) yuvarlanır. Yani, sonuçlar en az 28. ondalık basamağa kadar kesinlik 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 decimal
dönüştürmeler taşma özel durumları üretebilir ve decimal
'den kayan nokta türlerine dönüştürmeler duyarlık kaybına veya taşma özel durumlarına neden olabilir. Bu nedenlerden dolayı, kayan nokta türleri ile decimal
arasında örtük dönüşümler yoktur ve açık dönüşümler olmadan, kayan nokta ve decimal
işleçleri 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 true
ve false
'dir. temsili false
§8.3.3'te açıklanmıştır.
true
'nin gösterimi belirtilmemiş olsa da, false
'nin gösteriminden farklı olacaktır.
bool
ve diğer değer türleri arasında standart dönüşümler mevcut değil. Özellikle, bool
türü belirgin ve ayrı olup, integral türlerinden ayrıdır; bir bool
değer, tam sayı değeri yerine kullanılamaz ve tam tersi de geçerli değildir.
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ğerinetrue
dönüştürülebilir. C# dilinde bu tür dönüştürmeler, bir integral veya kayan nokta değeri açıkça sıfırla karşılaştırılarak veya nesne başvurusu açıkçanull
ile karşılaştırılarak gerçekleştirilir. dipnot
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
, sbyte
, short
, ushort
, int
, uint
, long
veya ulong
şeklinde temel bir türe sahip olmalıdır. 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)
; 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...Tn
System.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, yedi veya daha fazla elemanlı demetler, demet öğelerine ek olarak, farklı bir System.ValueTuple<T1, ..., T7, TRest>
türü kullanarak kalan öğelerin iç içe değerini kapsayan Rest
alanına sahip genel bir yapı türü System.ValueTuple<...>
ile temsil edilir. Bu tür iç içe geçme, ö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 kümelenmiş tür olarak kabul edilmez. Yediden fazla ek alan gerektiğinde, System.ValueTuple<T1, ..., T7, TRest>
özyinelemeli olarak kullanılır.
Bir tanımlama grubu türü içindeki öğe adları ayrı olmalıdır. formunItemX
X
, 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 X
belirtilen 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 tuple 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 new
oluşturulan bir türe uygulanarak ValueTuple<...>
oluşturulabilir.
Tuple öğeleri, Item1
, Item2
gibi adlarla genel alanlardır ve bir tuple değeri üzerindeki üye erişimi (§12.8.7) yoluyla erişilebilir. Ayrıca, demet türünün bir öğenin adı varsa, o öğ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 konumunaItem...
karşılık gelen adla doğrudan erişilebilir. dipnot
Ö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}");
pair1
,pair2
vepair3
için tanımlama grubu türlerinin hepsi geçerlidir; tanımlama grubu türü öğelerinin hiçbirine, bazısına veya tümüne ad verilebilir.Adların
pair4
ve konumlarının eşleşmesi nedeniyle için tanımlama grubu türüItem1
geçerlidir, ancak adlarItem2
vepair5
Item2
eşleşmediğinden için tanımlama grubu türüneItem123
izin verilmez.
pair6
vepair7
bildirimleri, tanım grubu türlerininValueTuple<...>
formundan oluşturulmuş türlerle değiştirilebilir olduğunu venew
işleminin bu türlerle kullanıldığı söz dizimine izin verildiğini gösterir.Son satır, demet öğelerine, konumlarına karşılık gelen isimle veya türde mevcutsa ilgili demet öğesi ismiyle 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 onun kısaltması (herhangi bir System.Nullable<T>
için) dışındaki herhangi bir değer türü, ayrıca boş değer atanamayan bir değer türü olarak kısıtlanan herhangi bir tür parametresidir (yani, değer türü kısıtlaması olan herhangi bir tür parametresi (T?
)).
System.Nullable<T>
türü, T
için değer türü kısıtlamasını belirtir; bu, null atanabilir bir değer türünün temel 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 değer alabilen 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 HasValue
true
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.
Bir örnekte HasValue
false
ise, o örneğin 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ına sebep 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 T
tek bir parametresi olan bir ortak oluşturucu vardır. Bir değer x
türünde T
verildiğinde, formun oluşturucu çağrısı
new T?(x)
T?
olan, Value
özelliği x
olan null olmayan bir örnek 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, null
literali ile T?
arasında (§10.2.7) ve T
ile T?
arasında (§10.2.6) kullanılabilir.
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 kutudan çıkarma kavramı, herhangi bir value_type değerinin türünü reference_type ve value_type değerine dönüştürülmesine izin vererek, bu iki tür arasında bir köprü oluşturur. Kutulama ve kutu açma, herhangi bir türdeki bir değerin nihayetinde bir object
olarak görülebileceği birleşik bir tür sistemini etkinleştirir.
Boks §10.2.9'da daha ayrıntılı olarak açıklanmıştır ve kutu açma §10.3.7'de açıklanmıştır.
8.4 Yapılı türler
8.4.1 Genel
Genel tür bildirimi, tür argümanlarını uygulayarak birçok farklı tür oluşturmak için "taslak" olarak kullanılan bağlanmamış bir genel türü kendi 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 türlere oluşturulmuş tür denir. 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).
Oluşturulmuş türler, ifadelerde basit isimler (§12.8.4) veya bir ü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, bir yapı 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
Enum olmayan bir yapısal tür unmanaged_type (§8.8) olarak kullanılmamalıdır.
8.4.2 Tür bağımsız değişkenleri
Tip bağımsız değişkeni listesindeki her bir bağımsız değişken sadece bir tiptir.
type_argument_list
: '<' type_argument (',' type_argument)* '>'
;
type_argument
: type
| type_parameter nullable_type_annotation?
;
Her tür bağımsız değişken, karşılık gelen tür parametresindeki (§15.2.5) kısıtlamaları karşılamalıdır. Tür parametresinin null atanabilirliği ile eşleşmeyen bir başvuru türü bağımsız değişkeni, yine de 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.
- Bir yapılı tür, ancak ve ancak tür bağımsız değişkenlerinden biri veya daha fazlası açık bir tür olduğunda açık bir türdür. İç içe geçen bir tür, yalnızca kendi tür bağımsız değişkenlerinden biri veya daha fazlası ya da içeren türlerden birinin tür bağımsız değişkenleri açık bir tür olduğunda 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 argümanları uygulanarak oluşturulan tamamlanmış yapılandırılmış 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.
İki kapalı yapı türü, aynı kapsamsız genel türden oluşturulmuşlarsa ve karşılık gelen tür parametrelerinin her biri arasında bir kimlik dönüşümü mevcutsa, kimlik dönüşümü yapılabilir (§10.2.2). 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.
Bağlı olmayan bir tür, tür bildirimi ile ilan edilen varlığa işaret eder. İ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
Bir yapılandırılmış tür veya genel yönteme her başvurulduğunda, verilen tür bağımsız değişkenleri, genel tür veya yöntem üzerinde belirtilen tür parametresi kısıtlamalarına göre kontrol edilir (§15.2.5). Her where
koşul 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şı denetlenir.
- Kısıtlama bir
class
türü, bir arabirim türü veya tür parametresiyse, kısıtlamada geçen tür parametrelerinin yerine geçen sağlanan tür argümanlarıylaC
'i temsil et. Kısıtlamayı karşılamak için, türünA
aşağıdakilerden birine göre türeC
dönüştürülebilir olması gerekir: - Kısıtlama başvuru türü kısıtlaması ()
class
ise, türA
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
veSystem.Enum
bu kısıtlamayı karşılayan başvuru türleridir. dipnot-
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ürA
aşağıdakilerden birini karşılamalı:-
A
birstruct
tür veyaenum
türdür, ancak null atanabilir bir değer türü değildir.
Not:
System.ValueType
veSystem.Enum
bu kısıtlamayı karşılamayan başvuru türleridir. dipnot-
A
değer türü kısıtlamasını (§15.2.5) içeren bir tür parametresidir.
-
- Eğer kısıtlama oluşturucu kısıtlaması
new()
ise, türüA
abstract
olmamalıdır 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
soyut olmayan ve parametresiz açıkça bildirilen genel bir oluşturucu içeren birclass
'dir. -
A
değildirabstract
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ü parametresi üzerindeT
kısıtlamayı belirleyerekT
'ün, temelclass
B<T>
tarafından uygulanan kısıtlamayı karşılaması ihtiyacı vardır. Buna karşılık,class
E
herhangi bir için uygulandığındanList<T>
kısıtlamaIEnumerable
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:
- Tür parametresi, bir temel sınıfı (§15.2.4.2) veya arabirimi (§18.2.4) bildirmek için doğrudan kullanılamaz.
- Tür parametrelerinde üye arama kuralları, tür parametresine uygulanan kısıtlamalara (varsa) bağlıdır. Bunlar §12.5'te ayrıntılı olarak yer alır.
- Tür parametresi için kullanılabilir dönüştürmeler, tür parametresine uygulanan kısıtlamalara (varsa) bağlıdır. Bunlar §10.2.12 ve §10.3.8 ile ayrıntılı olarak anlatılır.
- Tür
null
parametresinin başvuru türü (§10.2.12) olarak bilinmesi dışında değişmez değer, tür parametresi tarafından verilen türe dönüştürülemez. Ancak, bunun yerine varsayılan ifade (§12.8.21) kullanılabilir. Ayrıca, değer türü kısıtlaması olmadığı sürece, tür parametresi tarafından verilen türe sahip bir değer karşılaştırılabilir==
ve!=
kullanılarak null ile (§12.12.7).- İfade
new
(§12.8.17.2), yalnızca tür parametresi bir constructor_constraint veya değer türü kısıtlaması (§15.2.5) ile kısıtlanmışsa tür parametresiyle kullanılabilir.- Tür parametresi öznitelik içinde herhangi bir yerde kullanılamaz.
- Tür parametresi, statik bir üyeyi veya iç içe türü tanımlamak için üye erişiminde (§12.8.7) veya tür adında (§7.8) kullanılamaz.
- Tür parametresi unmanaged_type (§8.8) olarak kullanılamaz.
dipnot
Tür olarak, tür parametreleri yalnızca bir derleme zamanı yapısıdır. Çalışma zamanında, her tip parametresi, genel tip bildirimine bir tip argümanı sağlayarak belirlenen bir çalışma zamanı tipine 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 System.Linq.Expressions.Expression<TDelegate>
değerleridir. Bu belirtimin geri kalanı için bu türlere kısaltması Expression<TDelegate>
kullanılarak başvurulacaktır.
Lambda ifadesinden temsilci türüne D
dö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ırExpression<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ürenx + 1
bir yönteme başvurur ve ifade ağacı exp ifadesi ifadesini açıklayan bir veri yapısınax => x + 1
başvurur.son örnek
Expression<TDelegate>
, Compile
türünde bir temsilci üreten 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 2
sahip 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
dipnot
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). - Tür çıkarımı (§12.6.3), her ikisi de aday olduğunda
dynamic
'iobject
'e tercih edecektir. -
dynamic
olarak kullanılamaz- object_creation_expression türü (§12.8.17.2)
- class_base (§15.2.4)
- predefined_type bir member_access içinde (§12.8.7.1)
- işleç
typeof
operatörünün işleneni - özellik argümanı
- 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
- arasında
object
vedynamic
-
dynamic
ileobject
değiştirildiğinde aynı olan yapılı türler arasında - ile değiştirirken
dynamic
aynı olan tanımlama grubu türleri arasındaobject
- arasında
-
object
vedynamic
'e ve bunlardan örtük ve açık dönüştürmeler de geçerlidir. - ile
dynamic
değiştirilirkenobject
aynı olan imzalar aynı imza olarak kabul edilir. - Türü
dynamic
, çalışma zamanında türündenobject
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
,float
double
veyadecimal
.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 olabilme durumu
8.9.1 Genel
Null atanabilir başvuru türü, null atanamayan başvuru türünebir 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 null
başvurusu olabilir.
nullable_type_annotation varlığı veya yokluğu, 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 değeri alabilirlik biçimi vardır.
-
nullable: Bir nullable referans türü olarak atanabilir
null
. Varsayılan null durumu belki-null'tır. -
null olmayan: Null olmayan referansa değer
null
atanmamalıdır. Varsayılan null durumu null değil.
Not: ve
R
türleriR?
, aynı temel türüyleR
temsil edilir. Bu temel türün değişkeni bir nesneye başvuru içerebilir veya değerinull
olabilir ve bu değer "başvuru yok" ifadesini gösterir. dipnot
Null atanabilir başvuru türü ile karşılık gelen null atanamayan başvuru türü arasındaki sözdizimsel ayrım, derleyicinin tanılama mesajları üretmesine olanak tanır. Bir derleyici, §8.2.1'de tanımlandığı gibi nullable_type_annotation olarak izin vermelidir. Tanılamalar uyarılarla sınırlı olmalıdır. Ne boş değer atanabilir ek açıklamaların varlığı ne de yokluğu ve ne de boş değer atanabilir bağlamın durumu, derleme zamanında oluşturulan tanılama iletilerindeki değişiklikler haricinde, bir programın derleme veya çalışma zamanı davranışını değiştiremez.
8.9.2 Null değer atanamayan başvuru türleri
Null atanamayan başvuru türü, T
formunda bir baş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 yerlerde muhtemelen null olan bir ifade kullanıldığında uyarılar oluşturulabilir.
8.9.3 Boş değer atanabilir başvuru türleri
Formu T?
olan bir referans türü (örneğin string?
), null yapılabilir bir referans türüdür. Null atanabilir bir değişkenin varsayılan null durumu null olabilir. Ek açıklamalar ?
, bu türdeki değişkenlerin null olabileceğini belirtir. 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. Nullable bağlam kontrolü için anotasyonlar (§8.9.4.3) ve nullable uyarılar (§8.9.4.4) için 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.
Nullable bağlam, kaynak kodu üzerinde nullable yönergeler (§6.5.9) ve/veya kaynak kodun dışındaki uygulamaya özgü bir mekanizma aracılığıyla belirtilebilir. Her iki yaklaşım da kullanılırsa, boş kabul edilebilir yönergeler, bir dış mekanizma aracılığıyla yapılan ayarları geçersiz kılar.
Null atanabilir bağlamın varsayılan durumu uygulamaya bağlıdır.
Bu tanım boyunca, boş değer atanabilir yönergeler içermeyen veya mevcut null atanabilir bağlam durumu hakkında bir ifade bulunmayan tüm C# kodlarının, hem ek açıklamaların hem de uyarıların etkin olduğu null atanabilir bir bağlamda 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. dipnot
8.9.4.2 Null yapılabilir devre dışı bırakma
Hem uyarı hem de ek açıklama bayrakları devre dışı bırakıldığında, null değer atanabilir bağlam devre dışı bırakılır.
Null atanabilir bağlam devre dışı bırakıldığında:
- Ek açıklaması olmayan başvuru türündeki bir değişken,
null
ile başlatıldığında veya onanull
değeri atandığında uyarı oluşturulmaz. - Başvuru türündeki bir değişkenin olasılıkla null değeri varsa uyarı oluşturulmaz.
- herhangi bir başvuru türü için
T
,?
içindekiT?
ek açıklama bir ileti oluşturur ve türüT?
,T
ile aynıdır. - Herhangi bir tür parametresi kısıtlaması
where T : C?
için,?
içinde yer alanC?
ek açıklaması bir ileti oluşturur ve türC?
,C
ile aynıdır. - Herhangi bir tür parametresi kısıtlaması
where T : U?
için,?
içinde yer alanU?
ek açıklaması bir ileti oluşturur ve türU?
,U
ile aynıdır. - Genel kısıtlama
class?
bir uyarı iletisi oluşturur. Tip parametresi bir referans tipi 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. dipnot
- 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 açıklamalar bayrağı etkinleştirildiğinde, null atanabilir bağlam açıklamalar olur.
Null atanabilir bağlam ek açıklamalar olduğunda:
- herhangi bir başvuru türü
T
için,?
içindeki ek açıklamaT?
bir null atanabilir tür olduğunu belirtirken, ek açıklamasızT?
null atanamaz. - Null değerlerle ilgili tanılama uyarıları üretilmez.
- Null-forgiving işleci
!
(§12.8.9), işlenenin analiz edilmiş 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 olabilen 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 yapılabilir referans türünü belirtmek için kullanılır. - null affeden işleci
!
(§12.8.9), işlenenin 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 yapılabilirliği etkinleştirme
Hem uyarı bayrağı hem de annotasyon bayrağı etkinleştirildiğinde, null yapılabilir bağlam etkinleştirilir.
Null atanabilir bağlam etkinleştirildiğinde:
- herhangi bir referans türü
T
için,?
içindekiT?
açıklamasıT?
'ü null yapılabilir bir tür haline getirir, oysa açıklamasızT
non-nullable'dır. - 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, belki null veya belki varsayılan olur.
- null'u görmezden gelen işleç
!
(§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
8.9.5.1 Genel
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.
8.9.5.2 Akış analizi
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 referans 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 olamayan referans türünün varsayılan null durumu null değildir.
Not: belirsiz varsayılan
string
, türün null değer atanamayan bir tür olması ve ifadenindefault(T)
null değer olması durumunda, 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. dipnot
Boş değer atanamayan bir başvuru türünün değişkeni (§9.2.1) başlatıldığında veya bir null değere sahip olabilecek bir ifadeye atandığında ve bu değişkenin ek açıklama bayrağının etkin olduğu bir metinde bildirildiğinde bir tanı 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 birNullReferenceException
oluştururdu. Bu, koddan önceif (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öntemin ilerleyen bölümlerinde kod, s
'nin null başvuru olup olmadığını denetler.
s
'nin null durumu, null kontrolü yapılmış blok kapandıktan sonra belki 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
'yu null olmayan bir değere ayarlamaz, bu yüzden derleyici bir uyarı verebilir. ÖzelliğinP
türü null atanamaz bir başvuru türü olduğundan özelliğe erişildiğinde uyarı olmaz. son örnek
Derleyici bir özelliği (§15.7) durumlu bir değişken olarak veya bağımsız alma ve ayarlama erişimcileri (§15.7.3) olarak değerlendirebilir.
Ö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,
DisappearingProperty
için yedek alanı okunduğunda null değerine ayarlanı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 NullReferenceException
oluş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
8.9.5.3 Tür dönüştürmeleri
Tanılama uyarıları oluşturan bir derleyici bu kurallara uygundur.
Not: Türlerdeki üst düzey veya iç içe null atanabilirlik açıklamalarındaki farklar, null atanamayan referans türü ile karşılık gelen null atanabilir tür arasında anlamsal bir fark olmadığından, türler arasında dönüştürmeye izin verilip verilmeyeceğini etkilemez. (§8.9.1). dipnot
Derleyici, dönüştürme daraltıldığında, iki tür arasında null atanabilirlik ek açıklamaları ya üst düzey ya da iç içe olarak farklılık gösterdiğinde bir uyarı verebilir.
Örnek: Üst düzey ek açıklamalarda farklılık gösteren türler
#nullable enable public class C { public void M1(string p) { _ = (string?)p; // No warning, widening } public void M2(string? p) { _ = (string)p; // Warning, narrowing _ = (string)p!; // No warning, suppressed } }
son örnek
Örnek: İç içe null atanabilirlik açıklamalarında farklılık gösteren türler
#nullable enable public class C { public void M1((string, string) p) { _ = ((string?, string?))p; // No warning, widening } public void M2((string?, string?) p) { _ = ((string, string))p; // Warning, narrowing _ = ((string, string))p!; // No warning, suppressed } }
son örnek
Derleyici, tür dönüştürmeleri için uyarı verilip verilmeyeceğini belirlemede arabirim varyansı (§18.2.3.3), temsilci varyansı (§20.4) ve dizi kovaryansı (§17.6) kurallarını izleyebilir.
#nullable enable public class C { public void M1(IEnumerable<string> p) { IEnumerable<string?> v1 = p; // No warning } public void M2(IEnumerable<string?> p) { IEnumerable<string> v1 = p; // Warning IEnumerable<string> v2 = p!; // No warning } public void M3(Action<string?> p) { Action<string> v1 = p; // No warning } public void M4(Action<string> p) { Action<string?> v1 = p; // Warning Action<string?> v2 = p!; // No warning } public void M5(string[] p) { string?[] v1 = p; // No warning } public void M6(string?[] p) { string[] v1 = p; // Warning string[] v2 = p!; // No warning } }
son örnek
Derleyici, değişken dönüşümüne izin verilmeyen türlerde her iki yönde de null durumu farklılık gösterdiğinde uyarı verebilir.
#nullable enable public class C { public void M1(List<string> p) { List<string?> v1 = p; // Warning List<string?> v2 = p!; // No warning } public void M2(List<string?> p) { List<string> v1 = p; // Warning List<string> v2 = p!; // No warning } }
son örnek
Koşullu normatif metnin sonu
ECMA C# draft specification