Aracılığıyla paylaş


12 Deyim

12.1 Genel

Bir ifade, işleçler ve işlenenler dizisidir. Bu yan tümce söz dizimini, işlenenlerin ve işleçlerin değerlendirilme sırasını ve ifadelerin anlamını tanımlar.

12.2 İfade sınıflandırmaları

12.2.1 Genel

bir ifadenin sonucu aşağıdakilerden biri olarak sınıflandırılır:

  • Bir değer. Her değerin ilişkili bir türü vardır.
  • Bir değişken. Aksi belirtilmedikçe, bir değişken açıkça yazılır ve değişkenin bildirilen türü olan ilişkili bir türe sahiptir. Örtük olarak yazılan değişkenin ilişkili türü yoktur.
  • Null sabit. Bu sınıflandırmaya sahip bir ifade örtük olarak başvuru türüne veya nullable değer türüne dönüştürülebilir.
  • Anonim bir işlev. Bu sınıflandırmaya sahip bir ifade örtük olarak uyumlu bir temsilci türüne veya ifade ağacı türüne dönüştürülebilir.
  • Bir demet. Her bir tuple, sabit sayıda öğeye sahiptir ve her bir öğe bir ifade ile isteğe bağlı bir tuple öğesi adına sahiptir.
  • Özellik erişimi. Her özellik erişimi, ilişkili bir türe sahiptir; bu da özelliğin türüdür. Ayrıca, özelliğe erişim bir örnek ifade ile ilişkili olabilir. Bir örnek özelliği erişimcisinin çağrılması durumunda, örnek ifadesinin değerlendirilmesi sonucu this tarafından temsil edilen bir örnek haline gelir (§12.8.14).
  • Dizin oluşturucu erişimi. Her dizin oluşturucu erişimi, dizin oluşturucunun öğe türü olarak ilişkili bir türe sahiptir. Ayrıca, dizin oluşturucu erişiminin ilişkili bir örnek ifadesi ve ilişkili bağımsız değişken listesi vardır. Dizinleyici erişiminin erişimcisi çağrıldığında, örnek ifadesinin değerlendirilmesi sonucu this (§12.8.14) ile temsil edilen örnek olur ve bağımsız değişken listesinin değerlendirilmesi sonucu da çağrının parametre listesi olur.
  • Hiç. bu durum, ifade voiddönüş türüne sahip bir yöntemin çağrılması olduğunda oluşur. Hiçbir şey olarak sınıflandırılan bir ifade yalnızca statement_expression (§13.7) bağlamında veya bir lambda_expression gövdesi (§12.21) olarak geçerlidir.

Daha büyük ifadelerin alt ifadeleri olarak ortaya çıkan ifadeler için, belirtilen kısıtlamalarla birlikte sonuç aşağıdakilerden biri olarak da sınıflandırılabilir:

  • Bir ad alanı. Bu sınıflandırmaya sahip bir ifade yalnızca bir member_access sol tarafı olarak görünebilir (§12.8.7). Başka bir bağlamda, ad alanı olarak sınıflandırılan bir ifade derleme zamanı hatasına neden olur.
  • Bir tür. Bu sınıflandırmaya sahip bir ifade yalnızca bir member_access sol tarafı olarak görünebilir (§12.8.7). Başka bir bağlamda, tür olarak sınıflandırılan bir ifade derleme zamanı hatasına neden olur.
  • Yöntem grubu, üye aramasından (§12.5) kaynaklanan aşırı yüklenmiş yöntemlerden oluşan bir kümedir. Yöntem grubunun ilişkili bir örnek ifadesi ve ilişkili tür bağımsız değişken listesi olabilir. Bir örnek yöntemi çağrıldığında, örnek ifadesini değerlendirmenin sonucu this (§12.8.14) ile temsil edilen örnek olur. Yöntem grubuna invocation_expression (§12.8.10) veya delegate_creation_expression (§12.8.17.5) izin verilir ve örtük olarak uyumlu bir temsilci türüne (§10.8) dönüştürülebilir. Başka bir bağlamda, yöntem grubu olarak sınıflandırılan bir ifade derleme zamanı hatasına neden olur.
  • Etkinliğe erişim sağlama. Her etkinlik erişimi, etkinliğin kendi türüne ilişkilidir. Ayrıca, olay erişimi ilişkili bir örnek ifadeye sahip olabilir. Olay erişimi ve += işleçlerinin sol işleneni -= olarak görünebilir (§12.23.5). Başka bir bağlamda, olay erişimi olarak sınıflandırılan bir ifade derleme zamanı hatasına neden olur. Bir örnek olay erişiminin erişimcisi çağrıldığında, örnek ifadesini değerlendirmenin sonucu this tarafından temsil edilen örnek olur (§12.8.14).
  • Bir ifadede özel durum oluşturmak için çeşitli bağlamlarda kullanılabilecek throw ifadesi. Throw ifadesi örtük bir dönüştürme ile herhangi bir türe dönüştürülebilir.

Özellik erişimi veya dizin oluşturucu erişimi, get erişimcisini veya küme erişimcisini çağırarak her zaman bir değer olarak yeniden sınıflandırılır. Belirli erişimci, özellik veya dizin oluşturucu erişiminin bağlamı tarafından belirlenir: Erişim bir atamanın hedefiyse, yeni bir değer atamak için küme erişimcisi çağrılır (§12.23.2). Aksi takdirde, geçerli değeri (§12.2.2) almak için get erişimcisi çağrılır.

örneği erişimcisi, bir örnek üzerinde özellik erişimi, bir örnek üzerinde olay erişimi veya bir dizinleyici erişimidir.

12.2.2 İfadelerin değerleri

İfade içeren yapıların çoğu, nihayetinde ifadenin bir değerbelirlemesini gerektirir. Bu gibi durumlarda, gerçek ifade bir ad alanı, tür, yöntem grubu veya hiçbir şey belirtirse, derleme zamanı hatası oluşur. Ancak, ifade bir özellik erişimi, dizin oluşturucu erişimi veya değişken belirtirse, özellik, dizin oluşturucu veya değişkenin değeri örtük olarak değiştirilir:

  • Bir değişkenin değeri, değişkeni tarafından tanımlanan depolama konumunda depolanan değerdir. Bir değişkenin değeri elde edilmeden önce mutlaka atanmış olması gerekir (§9.4), aksi takdirde bir derleme zamanı hatası oluşur.
  • Özellik erişim ifadesinin değeri, özelliğin get erişimcisini çağırarak elde edilir. Özelliğin get erişimcisi yoksa derleme anında bir hata oluşur. Aksi takdirde, bir işlev üyesi çağrısı (§12.6.6) gerçekleştirilir ve çağrının sonucu özellik erişim ifadesinin değeri olur.
  • Dizin oluşturucu erişim ifadesinin değeri, dizin oluşturucunun get erişimcisini çağırarak elde edilir. Dizin oluşturucunun get erişimcisi yoksa derleme zamanı hatası oluşur. Aksi takdirde, bir işlev üyesi çağırması (§12.6.6) dizin oluşturucu erişim ifadesiyle ilişkilendirilmiş bağımsız değişken listesiyle gerçekleştirilir ve çağrının sonucu dizin oluşturucu erişim ifadesinin değeri olur.
  • Bir bileşik ifadesinin değeri, bileşik ifadesinin türüne örtük bir bileşik dönüştürmesi (§10.2.13) uygulanarak elde edilir. Türü olmayan bir tuple ifadesinin değerini almak bir hatadır.

12.3 Statik ve Dinamik Bağlama

12.3.1 Genel

Bağlama, ifadelerin türüne veya değerine (bağımsız değişkenler, işlenenler, alıcılar) göre bir işlemin neye başvurduğu belirleme işlemidir. Örneğin, bir metot çağrısının bağlanması, alıcı nesnenin türüne ve bağımsız değişkenlere göre belirlenir. Bir işlecin bağlanması, işlenenlerinin türüne göre belirlenir.

C# dilinde bir işlemin bağlaması genellikle, alt ifadelerinin derleme zamanı türüne göre derleme zamanında belirlenir. Benzer şekilde, bir ifade hata içeriyorsa, hata algılanır ve derleme zamanında bildirilir. Bu yaklaşım,statik bağlama olarak bilinir.

Ancak, bir ifadede dinamik ifade varsa (yani, türü dynamic) bu, katıldığı herhangi bir bağıntının derleme zamanında sahip olduğu tür yerine çalışma zamanı türüne dayalı olması gerektiğini gösterir. Bu nedenle, böyle bir işlemin bağlanması, programın çalışması sırasında işlemin yürütüleceği zamana kadar ertelenir. Bu,dinamik bağlama olarak adlandırılır.

Bir işlem dinamik olarak bağlı olduğunda, derleme zamanında tarafından çok az denetim gerçekleştirilir veya hiç yapılmaz. Bunun yerine, çalışma zamanı bağlaması başarısız olduğunda, hatalar çalışma zamanında istisna olarak bildirilir.

C# dilinde aşağıdaki işlemler bağlamaya tabidir:

  • Üye erişimi: e.M
  • Yöntem çağırma: e.M(e₁,...,eᵥ)
  • Temsilci çağırma: e(e₁,...,eᵥ)
  • Öğe erişimi: e[e₁,...,eᵥ]
  • Nesne oluşturma: yeni C(e₁,...,eᵥ)
  • Aşırı yüklenmiş tekli işleçler: +, -, ! (yalnızca mantıksal olumsuzlama), ~, ++, --, true, false
  • Aşırı yüklenmiş ikili işleçler: +, -, *, /, %, &, &&, |, ||, ??, ^, <<, >>, ==, !=, >, <, >=, <=
  • Atama işleçleri: =, = ref, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, ??=
  • Örtük ve açık dönüştürmeler

Hiçbir dinamik ifade söz konusu olmadığında, C# varsayılan olarak statik bağlamayı kullanır; bu da seçim işleminde alt ifadelerin derleme zamanı türlerinin kullanıldığı anlamına gelir. Ancak, yukarıda listelenen işlemlerdeki alt ifadelerden biri dinamik bir ifade olduğunda, işlem bunun yerine dinamik olarak bağlıdır.

Bir yöntem çağrısı dinamik olarak bağlıysa ve alıcı da dahil olmak üzere parametrelerden herhangi biri giriş parametreleriyse derleme zamanı hatasıdır.

12.3.2 Bağlama Zamanı

Statik bağlama derleme zamanında, dinamik bağlama ise çalışma zamanında gerçekleşir. Aşağıdaki alt ifadelerde bağlama zamanı terimi, bağlamanın ne zaman gerçekleştiğine bağlı olarak derleme zamanını veya çalışma zamanını ifade eder.

Örnek: Statik ve dinamik bağlama ve bağlama süresi kavramları aşağıda gösterilmiştir:

object o = 5;
dynamic d = 5;
Console.WriteLine(5); // static binding to Console.WriteLine(int)
Console.WriteLine(o); // static binding to Console.WriteLine(object)
Console.WriteLine(d); // dynamic binding to Console.WriteLine(int)

İlk iki çağrı statik olarak bağlanır: Console.WriteLine için aşırı yükleme seçimi, bağımsız değişkenlerinin derleme zamanı türüne göre yapılır. Bu nedenle bağlama zamanı derleme zamanı.

Üçüncü çağrı dinamik olarak bağlıdır: Console.WriteLine aşırı yüklemesi, bağımsız değişkeninin çalışma zamanı türüne göre seçilir. Bunun nedeni, bağımsız değişkenin dinamik bir ifade olması ve derleme zamanı türünün de bu şekilde olmasıdır. Bu nedenle, üçüncü çağrının bağlama süresi çalışma zamanıdır.

son örnek

12.3.3 Dinamik bağlama

Bu alt bildirim bilgilendiricidir.

Dinamik bağlama, C# programlarının, C# türü sisteminin normal kurallarına uymayan nesneler gibi dinamik nesnelerle etkileşim kurmasına olanak tanır. Dinamik nesneler, farklı tür sistemlerine sahip diğer programlama dillerindeki nesneler veya farklı işlemler için kendi bağlama semantiğini uygulamak üzere program aracılığıyla ayarlanan nesneler olabilir.

Bir dinamik nesnenin kendi semantiğini uyguladığı mekanizma, uygulama tanımlıdır. Belirli bir arabirim, yine uygulamaya göre tanımlanan, dinamik nesneler tarafından C# çalışma zamanına özel semantiklere sahip olduklarını işaret etmek için uygulanır. Bu nedenle, dinamik bir nesnedeki işlemler dinamik olarak bağlı olduğunda, burada belirtilen C#'ın bağlama semantiği yerine kendi bağlama semantiği devreye girer.

Dinamik bağlamanın amacı dinamik nesnelerle birlikte çalışılmasına izin vermek olsa da, C# dinamik olup olmadıkları farketmeksizin tüm nesnelerde dinamik bağlamaya izin verir. Bu, dinamik nesnelerin daha sorunsuz tümleştirilmesine olanak tanır, zira üzerlerindeki işlemlerin sonuçları her zaman dinamik nesneler değildir ve derleme zamanında programcı tarafından bilinmeyen bir türdedir. Ayrıca, dinamik bağlama, hiçbir nesne dinamik nesne olmadığında bile hataya açık yansıma tabanlı kodu ortadan kaldırmaya yardımcı olabilir.

12.3.4 Alt ifade türleri

Bir işlem statik olarak bağlandığında, bir alt ifadenin türü (örneğin, bir alıcı, bağımsız değişken, dizin veya işlenen) her zaman bu ifadenin derleme dönemi türü olarak kabul edilir.

Bir işlem dinamik olarak bağlı olduğunda, alt ifadenin türü, alt ifadenin derleme zamanı türüne bağlı olarak farklı şekillerde belirlenir:

  • Derleme zamanı türü dinamik alt ifadesi, ifadenin çalışma zamanında değerlendirilen gerçek değerin türüne sahip olarak kabul edilir
  • Derleme zamanı türü tür parametresi olan bir alt ifade, çalışma zamanında tür parametresinin bağlı olduğu türe sahip olarak kabul edilir
  • Aksi takdirde, alt ifadenin derleme zamanı türüne sahip olduğu kabul edilir.

12.4 İşleçler

12.4.1 Genel

İfadeler operandlar ve işleçlerden oluşturulur. Bir ifadenin operatörleri, işlenenlere hangi işlemlerin uygulanacağını belirtir.

Örnek: İşleçlere örnek olarak +, -, *, /ve newverilebilir. İşlenenlere örnek olarak değişmez değerler, alanlar, yerel değişkenler ve ifadeler verilebilir. son örnek

Üç tür işleç vardır:

  • Tekli işleçler. Unary operatörler bir işlenen alır ve önek gösterimi (–xgibi) veya son ek gösterimi (x++gibi) kullanır.
  • İkili işleçler. İkili işleçler iki işlem içeren ve tümü infix gösterimini (x + ygibi) kullanır.
  • Üçüncül işleç. ?:için sadece bir üçüncül işleç vardır; üç işlenen alır ve ara notasyon (c ? x : y) kullanır.

bir ifadedeki işleçlerin değerlendirilme sırası, işleçlerin önceliği ve ilişkilendirme (§12.4.2) tarafından belirlenir.

bir ifadedeki işlenenler soldan sağa değerlendirilir.

Örnek: F(i) + G(i++) * H(i)'de, yöntem F eski ideğeri kullanılarak çağrılır, ardından yöntem G eski ideğeriyle çağrılır ve son olarak yöntem H yeni i değeriyle çağrılır. Bu, işleç önceliğinden bağımsız ve onunla ilgili değildir. son örnek

Bazı işleçler aşırı yüklenebilir. İşleç aşırı yüklemesi (§12.4.3), işlenenlerden birinin veya her ikisinin kullanıcı tanımlı bir sınıf veya yapı türünde olduğu işlemler için kullanıcı tanımlı işleç uygulamalarının belirtilmesine izin verir.

12.4.2 İşleç önceliği ve ilişkilendirme

bir ifade birden çok işleç içerdiğinde, işleçlerin önceliği tek tek işleçlerin değerlendirilme sırasını denetler.

Not: Örneğin, x + y * z işleci ikili x + (y * z) işlecinden daha yüksek önceliğe sahip olduğundan * ifadesi + olarak değerlendirilir. son notu

Bir işlecin önceliği, ilişkili dil bilgisi üretiminin tanımıyla oluşturulur.

Not: Örneğin, bir additive_expression veya + işleçleriyle ayrılmış bir -dizisinden oluşur; böylece + ve - işleçleri *, /ve % işleçlerinden daha düşük önceliklidir. son notu

Not: Aşağıdaki tabloda tüm işleçler en yüksekten en düşüğe öncelik sırasına göre özetlenmiştir:

Alt Fıkra Kategori İşleçleri
§12.8 Birincil x.y x?.y f(x) a[x] a?[x] x++ x-- x! new typeof default checked unchecked delegate stackalloc
§12.9 Tekli + - !x ~ ^ ++x --x (T)x await x
§12.10 Aralık ..
§12.11 Şalter switch { … }
§12.12 Çarpan * / %
§12.12 Katkı + -
§12.13 Vardiya << >>
§12.14 İlişkisel ve tür testleri < > <= >= is as
§12.14 Eşitlik == !=
§12.15 Mantıksal VE &
§12.15 Mantıksal XOR ^
§12.15 Mantıksal VEYA \|
§12.16 Koşullu VE &&
§12.16 Koşullu VEYA \|\|
§12.17 ve §12.18 Null birleştirme işleci ve throw ifadesi ?? throw x
§12.20 Koşullu ?:
§12.23 ve §12.21 Atama ve lambda ifadesi = = ref *= /= %= += -= <<= >>= &= ^= \|= => ??=

son notu

Aynı önceliğe sahip iki işleç arasında bir operand yer aldığında, işleçlerin ilişkilendiriciliği işlemlerin hangi sırayla yapılacağını kontrol eder.

  • Atama işleçleri, aralık işleci ve null birleşim işleci dışında, tüm ikili işleçler soldan sağa doğru gerçekleştirilir.

    Örnek: x + y + z(x + y) + zolarak değerlendirilir. son örnek

  • Atama işleçleri, null birleşim işleci ve koşullu işleç (?:) sağdan ilişkili , yani işlemler sağdan sola gerçekleştirilir.

    Örnek: x = y = zx = (y = z)olarak değerlendirilir. son örnek

  • Aralık işleci ilişkilendirilemez, yani bir aralık işlecinin solu veya sağ işleneni range_expression olmayabilir.

    Örnek: İlişkisel olmayan olduğu için x..y..z hem hem x..(y..z) de .. geçersizdir. son örnek

Öncelik ve ilişkisellik parantezler kullanılarak denetlenebilir.

Örnek: x + y * z önce y ile z çarpar ve ardından sonucu xekler, ancak (x + y) * z önce x ve y ekler ve ardından sonucu zile çarpar. son örnek

12.4.3 İşleç aşırı yüklemesi

Tüm birli ve ikili işleçler önceden tanımlanmış uygulamalara sahiptir. Ayrıca, kullanıcı tanımlı uygulamalar sınıflara ve yapılara işleç bildirimleri (§15.10) dahil edilerek de tanıtılabilir. Kullanıcı tanımlı işleç uygulamaları her zaman önceden tanımlanmış işleç uygulamalarından önceliklidir: Yalnızca, önceden tanımlanmış hiçbir kullanıcı tanımlı işleç uygulaması yoksa, önceden tanımlanmış işleç uygulamaları §12.4.4 ve §12.4.5.'de açıklandığı gibi dikkate alınacaktır.

Aşırı yüklenebilir birli işleçlerşunlardır:

+ - ! (yalnızca mantıksal olumsuzlama) ~ ++ -- true false

Yalnızca yukarıda listelenen işleçler aşırı yüklenebilir. Özellikle, null-forgiving işlecini (sonek !, §12.8.9) veya birli dizinden uç işlecini (ön ek ^, (§12.9.6) aşırı yüklemek mümkün değildir.

Not: ve true ifadelerde açıkça kullanılmasa false da (ve bu nedenle §12.4.2'deki öncelik tablosuna dahil edilmese de), bunlar çeşitli ifade bağlamında çağrıldıkları için işleç olarak kabul edilirler: Boole ifadeleri (§12.26) ve koşullu (§12.20) ve koşullu mantıksal işleçleri (§12.16) içeren ifadeler. son notu

Aşırı yüklenebilir ikili işleçlerşunlardır:

+ - * / % & | ^ << >> == != > < <= >=

Yalnızca yukarıda listelenen işleçler aşırı yüklenebilir. Özellikle, üye erişimini, yöntem çağrısını veya .., =, &&, , ||, ??, , ?:, =>, checked, , uncheckednew, , typeof, default, asve is işleçlerini aşırı yüklemek mümkün değildir.

İkili işleç aşırı yüklendiğinde, varsa buna karşılık gelen bileşik atama işleci de örtük olarak aşırı yüklenir.

Örnek: İşleç *'nin aşırı yüklenmesi, aynı zamanda *=işlecin de aşırı yüklenmesidir. Bu, §12.23'te daha ayrıntılı olarak açıklanmıştır. son örnek

Atama işlecinin kendisi (=) aşırı yüklenemez. Atama her zaman bir değerin basit depolarını bir değişkende gerçekleştirir (§12.23.2).

(T)xgibi dönüştürme işlemleri, kullanıcı tanımlı dönüştürmeler (§10.5) sağlayarak aşırı yüklenir.

Not: Kullanıcı tanımlı dönüştürmeler is veya as işleçlerinin davranışını etkilemez. son notu

a[x]gibi öğe erişimi aşırı yüklenebilir bir işleç olarak kabul edilmez. Bunun yerine, kullanıcı tanımlı dizin oluşturma dizin oluşturucular (§15.9) aracılığıyla desteklenir.

İfadelerde işleçlere işleç gösterimi kullanılarak başvurulur ve bildirimlerde işlevsel gösterimi kullanılarak işleçlere başvurulur. Aşağıdaki tabloda, tekli ve ikili işleçler için işleç ve işlev gösterimi arasındaki ilişki gösterilmektedir. İlk girdide , «op» aşırı yüklenebilir birli ön ek işlecini belirtir. İkinci girdide, «op» tekli artkı ++ ve -- operatörlerini belirtir. Üçüncü girdide, «op» aşırı yüklenebilir ikili işleçleri belirtir.

Not: ++ ve -- işleçlerini aşırı yükleme örneği için bkz. §15.10.2. son notu

İşleci gösterimi Fonksiyonel gösterim
«op» x operator «op»(x)
x «op» operator «op»(x)
x «op» y operator «op»(x, y)

Kullanıcı tanımlı işleç bildirimleri her zaman en az bir parametrenin işleç bildirimini içeren sınıf veya yapı türünde olmasını gerektirir.

Not: Bu nedenle, kullanıcı tanımlı bir işlecin önceden tanımlanmış işleçle aynı imzaya sahip olması mümkün değildir. son notu

Kullanıcı tanımlı işleç bildirimleri bir işlecin söz dizimini, önceliğini veya ilişkilendirmesini değiştiremez.

Örnek: / işleci her zaman bir ikili işleçtir, her zaman §12.4.2'de belirtilen öncelik düzeyine sahiptir ve her zaman sol ilişkilendirilebilir. son örnek

Not: Kullanıcı tanımlı bir işlecin istediği herhangi bir hesaplamayı gerçekleştirmesi mümkün olsa da, sezgisel olarak beklenenler dışında sonuçlar üreten uygulamalar kesinlikle önerilmez. Örneğin, işleç == uygulamasının eşitlik için iki işleneni karşılaştırması ve uygun bir bool sonucu döndürmesi gerekir. son notu

§12.9 ile §12.23 arasında tek tek işleçlerin açıklamaları, işleçlerin önceden tanımlanmış uygulamalarını ve her işleç için geçerli olan ek kuralları belirtir. Açıklamalarda geçen tekli operatör aşırı yükleme çözümlemesi, ikili operatör aşırı yükleme çözümlemesi, sayısal yükseltmeve yükseltilmiş operatör tanımları, aşağıdaki alt başlıklarda açıklanmaktadır.

12.4.4 Tekil işleç aşırı yükleme çözünürlüğü

«op» x veya x «op»biçimindeki bir işlem, burada «op» aşırı yüklenebilir bir tekli işleçtir ve xXtüründe bir ifadedir:

  • İşlem X için operator «op»(x) tarafından sağlanan aday kullanıcı tanımlı işleç kümesi, §12.4.6kuralları kullanılarak belirlenir.
  • Kullanıcı tanımlı aday işleç kümesi boş değilse, bu işlem için aday işleç kümesi olur. Aksi takdirde, genişletilmiş halleri de dahil, tanımlı ikili operator «op» uygulamaları işlemin aday operatörleri kümesi haline gelir. Belirli bir işlecin önceden tanımlanmış uygulamaları, işlecin açıklamasında belirtilir. Bir sabit listesi veya temsilci türü tarafından sağlanan önceden tanımlanmış işleçler, bu kümeye yalnızca bağlama zamanı türü (veya null atanabilir bir türse temel tür), işlenenin sabit listesi veya temsilci türü olduğunda eklenir.
  • §12.6.4 aşırı yükleme çözümleme kuralları, (x)bağımsız değişken listesi açısından en iyi işleci seçmek için aday işleç kümesine uygulanır ve bu işleç aşırı yükleme çözümleme işleminin sonucu olur. Aşırı yükleme çözümlemesi tek bir en iyi işleci seçemezse bağlama zamanı hatası oluşur.

12.4.5 İkili işleç aşırı yükleme çözme

x «op» ybiçimindeki bir işlem; burada «op» aşırı yüklenebilir bir ikili işleçtir, xXtüründe bir ifadedir ve yYtüründe bir ifadedir:

  • İşlem X için Y ve operator «op»(x, y) tarafından sağlanan aday kullanıcı tanımlı işleç kümesi belirlenir. Küme, her biri Xkuralları kullanılarak belirlenen, Y tarafından sağlanan aday işleçlerinin ve tarafından sağlanan aday işleçlerinin birleşiminden oluşur. Birleştirilmiş küme için adaylar aşağıdaki gibi birleştirilir:
    • X ve Y kimlik dönüştürülebilirse veya X ve Y ortak bir temel türden türetilmişse, paylaşılan aday işleçleri birleştirilmiş kümede yalnızca bir kez gerçekleşir.
    • X ile Yarasında bir kimlik dönüşümü varsa, «op»Y tarafından sağlanan Y işleci, «op»X tarafından sağlanan X ile aynı dönüş türüne sahip olur ve «op»Y'nın işlenen türleri, karşılık gelen «op»X işlenen türlerine kimlik dönüşümüne sahiptir ve kümede yalnızca «op»X oluşur.
  • Kullanıcı tanımlı aday işleç kümesi boş değilse, bu işlem için aday işleç kümesi olur. Aksi takdirde, genişletilmiş halleri de dahil, tanımlı ikili operator «op» uygulamaları işlemin aday operatörleri kümesi haline gelir. Belirli bir işlecin önceden tanımlanmış uygulamaları, işlecin açıklamasında belirtilir. Önceden tanımlanmış numaralandırma ve temsilci işleçleri için, yalnızca işlenenlerden birinin bağlama zamanı türü olan bir numaralandırma veya temsilci türü tarafından sağlanan işleçler dikkate alınır.
  • §12.6.4 aşırı yükleme çözümleme kuralları, (x, y)bağımsız değişken listesi açısından en iyi işleci seçmek için aday işleç kümesine uygulanır ve bu işleç aşırı yükleme çözümleme işleminin sonucu olur. Aşırı yükleme çözümlemesi tek bir en iyi işleci seçemezse bağlama zamanı hatası oluşur.

12.4.6 Aday kullanıcı tanımlı işleçler

Bir tür T ve bir işlem operator «op»(A)verildiğinde, burada «op» aşırı yüklenebilen bir işleç ve A bir bağımsız değişken listesidir, işleç T için «op»(A) tarafından sağlanan aday kullanıcı tanımlı işleç kümesi şöyle belirlenir:

  • T₀türünü belirleyin. T null atanabilir bir değer türüyse, T₀ onun temel türüdür; aksi takdirde, T₀, Tile eşittir.
  • operator «op»'deki tüm T₀ bildirimleri ve bu tür işleçlerin kaldırılan tüm biçimleri için, bağımsız değişken listesiyle ilgili olarak en az bir işleç (A) geçerliyse, aday işleçler kümesi T₀'deki ilgili tüm işleçlerden oluşur.
  • Aksi takdirde, T₀ ile objecteşitse, aday işleç kümesi boştur.
  • Aksi takdirde, T₀ tarafından sağlanan aday işleçler kümesi, T₀'in doğrudan temel sınıfı veya T₀ bir tür parametresiyse, T₀'nin etkin temel sınıfı tarafından sağlanan aday işleçler kümesidir.

12.4.7 Sayısal yükseltmeler

12.4.7.1 Genel

Bu alt bildirim bilgilendiricidir.

§12.4.7 ve alt modülleri aşağıdakilerin birleştirilmiş etkisinin bir özetidir:

  • örtük sayısal dönüştürmeler için kurallar (§10.2.3);
  • daha iyi dönüştürme kuralları (§12.6.4.7); ve
  • kullanılabilir aritmetik (§12.12), ilişkisel (§12.14) ve integral mantıksal (§12.15.2) işleçleri.

Sayısal yükseltme, önceden tanımlanmış birli ve ikili sayısal işleçlerin operandlarının belirli örtük dönüştürmelerini otomatik olarak gerçekleştirmeyi içerir. Sayısal yükseltme ayrı bir mekanizma değil, önceden tanımlanmış işleçlere aşırı yükleme çözümlemesi uygulamanın bir etkisidir. Sayısal yükseltme özellikle kullanıcı tanımlı işleçlerin değerlendirilmesini etkilemez, ancak kullanıcı tanımlı işleçler benzer etkiler sergileyecek şekilde uygulanabilir.

Sayısal yükseltme örneği olarak, ikili * işlecinin önceden tanımlanmış uygulamalarını göz önünde bulundurun:

int operator *(int x, int y);
uint operator *(uint x, uint y);
long operator *(long x, long y);
ulong operator *(ulong x, ulong y);
float operator *(float x, float y);
double operator *(double x, double y);
decimal operator *(decimal x, decimal y);

Bu işleç kümesine aşırı yükleme çözümleme kuralları (§12.6.4) uygulandığında, bunun etkisi işlenen türlerinden örtük dönüştürmelerin bulunduğu işleçlerden ilkini seçmektir.

Örnek: b * s bir b ve byte'in solduğu shortişlemi için, aşırı yükleme çözümlemesi en iyi işleç olarak operator *(int, int)'yi seçer. Sonuç olarak, etki, b ve s'in int'ye dönüştürülmesi ve sonucun türünün intolmasıdır. Benzer şekilde, i * dişlemi için, i bir int ve d bir doubleolduğunda, overload çözünürlük en iyi işleç olarak operator *(double, double)'yı seçer. son örnek

Bilgilendirici metin sonu.

12.4.7.2 Tekil sayısal yükseltmeler

Bu alt bildirim bilgilendiricidir.

Tekil sayısal yükseltme, önceden tanımlanmış +, -ve ~ tekli işleçlerinin işlenenleri için gerçekleşir. Tekli sayısal dönüşüm, yalnızca sbyte, byte, short, ushortveya char türündeki işlenenlerin inttürüne dönüştürülmesini içerir. Ayrıca, birli – işleci için birleşik sayısal yükseltme, uint türündeki işlenenleri longtürüne dönüştürür.

Bilgilendirici metin sonu.

12.4.7.3 İkili sayısal yükseltmeler

Bu alt bildirim bilgilendiricidir.

önceden tanımlanmış +, -, *, /, %, &, |, ^, ==, !=, >, <, >=ve <= ikili işleçleri için ikili sayısal yükseltme gerçekleşir. İkili sayısal yükseltme, örtük olarak her iki işleneni de ortak bir türe dönüştürür; bu tür, ilişkisel olmayan işleçler durumunda, aynı zamanda işlemin sonuç türü olur. İkili sayısal yükseltme, aşağıdaki kuralların burada göründükleri sırayla uygulanmasından oluşur:

  • İşlenenlerden biri decimaltüründeyse, diğer işlenen decimaltürüne dönüştürülür veya diğer işlenen float veya doubletüründeyse bağlama zamanı hatası oluşur.
  • Aksi takdirde, işlenenlerden biri double türündeyse, diğer işlenen double türüne dönüştürülür.
  • Aksi takdirde, işlenenlerden biri float türündeyse, diğer işlenen float türüne dönüştürülür.
  • Aksi takdirde, işlenenlerden biri ulongtüründeyse, diğer işlenen ulongtürüne dönüştürülür veya diğer işlenen type sbyte, short, intveya longise bağlama zamanı hatası oluşur.
  • Aksi takdirde, işlenenlerden biri long türündeyse, diğer işlenen long türüne dönüştürülür.
  • Aksi takdirde, işlenenlerden biri uint türündeyse ve diğer işlenen sbyte, shortveya inttüründeyse, her iki işlenen de longtürüne dönüştürülür.
  • Aksi takdirde, işlenenlerden biri uint türündeyse, diğer işlenen uint türüne dönüştürülür.
  • Aksi takdirde, her iki işlenen de int türüne dönüştürülür.

Not: İlk kural, decimal türünü double ve float türleriyle karıştıran işlemlere izin vermemektedir. Kural, decimal türü ile double ve float türleri arasında örtük dönüştürme olmamasından kaynaklanmıştır. son notu

Not: Ayrıca, diğer işlenen imzalı bir tam sayı türünde olduğunda bir işlenenin ulong türünde olması mümkün değildir. Bunun nedeni, hem ulong'ın tam sayılarının tam aralığını hem de imzalı tam sayı türlerini temsil eden bir tam sayı türünün olmamasıdır. son notu

Yukarıdaki her iki durumda da, bir işleneni diğer işlenenle uyumlu bir türe açıkça dönüştürmek için bir dönüştürme ifadesi kullanılabilir.

Örnek: Aşağıdaki kodda

decimal AddPercent(decimal x, double percent) =>
    x * (1.0 + percent / 100.0);

bir decimal bir doubleile çarpılamadığından bağlama zamanı hatası oluşur. Hata, ikinci işleneni aşağıdaki gibi açıkça decimal'a dönüştürerek çözülür:

decimal AddPercent(decimal x, double percent) =>
    x * (decimal)(1.0 + percent / 100.0);

son örnek

Bilgilendirici metin sonu.

12.4.8 Kaldırılan operatörler

Kaldırılan işleç, null atanamayan bir değer türü üzerinde çalışan önceden tanımlanmış ve kullanıcı tanımlı işleçlerin de bu türdeki null atanabilir formla kullanılmasına izin verir. Yükseltilmiş işleçler, aşağıda açıklandığı gibi belirli gereksinimleri karşılayan önceden tanımlanmış ve kullanıcı tanımlı işleçlerden oluşturulur.

  • birli işleçler +, ++, -, --, ! (mantıksal olumsuzlama), ^ve ~için işlenen ve sonuç türlerinin ikisi de null atanamaz değer türleriyse, bir işlecin yükseltilmiş bir biçimi vardır. Yükseltilmiş form, işlenene ve sonuç türlerine tek bir ? değiştirici eklenerek oluşturulur. Eğer işlenen null ise, kaldırılan işleç bir null değeri üretir. Aksi takdirde, yükseltilen operatör, işlenenin paketini açar, alttaki operatörü uygular ve sonucu yeniden paketler.
  • İşlenen ve sonuç türlerinin tümü null değer türü değilse , +-*/%&|, , , ^, ..ve <<ikili işleçleri >>için bir işlecin yükseltilmiş biçimi vardır. Kaldırılan form, her operatöre ve sonuç türüne tek bir ? değiştirici eklenerek oluşturulur. Kaldırılan işleç, işlenenlerden biri veya her ikisi null ise bir null değer üretir (& açıklandığı gibi türün | ve bool? işleçleri olan bir özel durum). Aksi takdirde, kaldırılan işleç işlenenleri kaldırır, temel işleci uygular ve sonucu sarmalar.
  • == ve !=eşitlik işleçleri için, işlenen türlerinin her ikisi de null atanamaz değer türleriyse ve sonuç türü boolise bir işlecin yükseltilmiş biçimi vardır. Yükseltilmiş form, her bir işlenen türüne tek bir ? değiştirici eklenerek oluşturulur. Kaldırılan işleç iki null değerini eşit kabul eder ve null değerininull olmayan herhangi bir değere eşit kabul etmez. Her iki işlenen denulldeğilse, yükseltilmiş işleç işlenenleri çözerek temel işleci uygular ve bool sonucunu üretir.
  • İlişkisel işleçler <, >, <=ve >=için, işlenen türlerinin her ikisi de null atanamaz değer türleriyse ve sonuç türü boolise, bir işlecin yükseltilmiş bir biçimi mevcut olabilir. Yükseltilmiş form, her bir işlenen türüne tek bir ? değiştirici eklenerek oluşturulur. Kaldırılan işleç, işlenenlerden biri veya her ikisi de falseise null değerini üretir. Aksi takdirde, yükseltilmiş operatör işlenenleri açar ve temel operatörü uygulayarak bool sonucunu üretir.

12.5 Üye arama

12.5.1 Genel

Üye araması, bir adın türü bağlamındaki anlamının belirlendiği işlemdir. Üye araması, bir ifadedeki bir simple_name (§12.8.4) veya member_access (§12.8.7) değerlendirmenin bir parçası olarak gerçekleşebilir. simple_name veya member_access, bir invocation_expression (§12.8.10.2) içinde primary_expression olarak yer alırsa, üyenin çağrıldığısöylenir.

Üye bir yöntem veya olaysa ya da bir temsilci türünün (§21) veya türün (dynamic) sabit, alan veya özelliğiyse, üyenin çağrılamaz olduğu söylenir.

Üye araması yalnızca üyenin adını değil, aynı zamanda üyenin sahip olduğu tür parametrelerinin sayısını ve üyenin erişilebilir olup olmadığını da dikkate alır. Üye arama amacıyla, genel yöntemler ve iç içe genel türler, ilgili bildirimlerinde belirtilen tür parametrelerinin sayısına sahiptir ve diğer tüm üyelerin tür parametreleri sıfırdır.

Bir N türünde, K tür bağımsız değişkenleri içeren ad T için bir üye araması aşağıdaki gibi işlenir:

  • İlk olarak, N adlı bir erişilebilir üye kümesi belirlenir:
    • T bir tür parametresiyse, küme, Niçin birincil kısıtlama veya ikincil kısıtlama (§15.2.5) olarak belirtilen türlerin her birinde T adlı erişilebilir üye kümelerinin ve Niçinde object adlı erişilebilir üye kümesinin birleşimidir.
    • Aksi takdirde, küme, devralınan üyeler ve içinde N adlı erişilebilir üyeler de dahil olmak üzere, Tiçinde N adlı tüm erişilebilir (object) üyelerinden oluşur. T yapılandırılmış bir türse, üye kümesi §15.3.3'de açıklandığı gibi tür bağımsız değişkenlerinin yerine konulmasıyla elde edilir. override değiştiricisi içeren üyeler kümenin dışında tutulur.
  • Ardından, K sıfırsa, bildirimleri tür parametrelerini içeren tüm iç içe türler kaldırılır. K sıfır değilse, farklı sayıda tür parametresine sahip tüm üyeler kaldırılır. K sıfır olduğunda, tür çıkarımı işlemi (§12.6.3) tür bağımsız değişkenlerini çıkarım yapabileceğinden tür parametrelerine sahip yöntemler kaldırılmaz.
  • Ardından, üye çağrılırsa, çağrılamayan tüm üyeler kümeden kaldırılır.
  • Ardından, diğer üyeler tarafından gizlenen üyeler kümeden kaldırılır. Kümede yer alan üye S.M için, S üyesinin bildirildiği tür M'dir ve aşağıdaki kurallar uygulanır:
    • M sabit, alan, özellik, olay veya numaralandırma üyesiyse, temel S türünde bildirilen tüm üyeler kümeden kaldırılır.
    • M bir tür bildirimiyse, temel S türünde bildirilen tüm tür dışı türler kümeden kaldırılır ve M temel türünde bildirilen S ile aynı sayıda tür parametresine sahip tüm tür bildirimleri kümeden kaldırılır.
    • M bir yöntemse, temel S türünde bildirilen yöntem dışı tüm üyeler kümeden kaldırılır.
  • Ardından, sınıf üyeleri tarafından gizlenen arabirim üyeleri kümeden kaldırılır. Bu adımın etkisi yalnızca T bir tür parametresiyse ve T hem object dışında etkili bir temel sınıfa hem de boş olmayan etkin arabirim kümesine (§15.2.5) sahipse geçerlidir. Kümedeki her üye S.M için, S, üye M'nin bildirildiği tür olduğunda, eğer S, objectdışında bir sınıf bildirimi ise aşağıdaki kurallar uygulanır:
    • M sabit, alan, özellik, olay, numaralandırma üyesi veya tür bildirimiyse, arabirim bildiriminde bildirilen tüm üyeler kümeden kaldırılır.
    • M bir yöntemse, arabirim bildiriminde bildirilen tüm yöntem dışı üyeler kümeden kaldırılır ve arabirim bildiriminde bildirilen M ile aynı imzaya sahip tüm yöntemler kümeden kaldırılır.
  • Son olarak, gizli üyeler kaldırıldıktan sonra aramanın sonucu belirlenir:
    • Küme, yöntem olmayan tek bir üyeden oluşuyorsa, bu üye aramanın sonucudur.
    • Aksi takdirde, küme yalnızca yöntemler içeriyorsa, bu yöntem grubu aramanın sonucudur.
    • Aksi takdirde, arama belirsizdir ve bağlama zamanı hatası oluşur.

Tür parametreleri ve arabirimleri dışındaki türlerdeki üye aramaları ve kesin olarak tek devralma olan arabirimlerdeki üye aramaları için (devralma zincirindeki her arabirimin tam olarak sıfır veya bir doğrudan temel arabirimi vardır), arama kurallarının etkisi yalnızca türetilmiş üyelerin aynı ada veya imzaya sahip temel üyeleri gizlemeleridir. Bu tür tek devralma aramaları hiçbir zaman belirsiz değildir. Birden çok devralma arabirimlerindeki üye aramalarından kaynaklanabilir belirsizlikler §19.4.11'de açıklanmıştır.

Not: Bu aşama yalnızca bir tür belirsizlik oluşturur. Üye araması bir yöntem grubunda sonuçlanırsa, yöntem grubunun daha fazla kullanımları belirsizlik nedeniyle başarısız olabilir; örneğin §12.6.4.1 ve §12.6.6.2. son notu

12.5.2 Temel türler

Üye arama amacıyla, bir T türünün aşağıdaki temel türlere sahip olduğu kabul edilir.

  • T object veya dynamicise T'ün temel türü olmaz.
  • T bir enum_typeise, T'ün temel türleri System.Enum, System.ValueTypeve objectsınıf türleridir.
  • T bir struct_typeise, temel T türleri System.ValueType ve objectsınıf türleridir.

    Notu: bir nullable_value_type, bir struct_type'tir (§8.3.1). son notu

  • T bir class_typeise, T'ün temel türleri, Tsınıf türü dahil object'ün temel sınıflarıdır.
  • T bir arabirim_türüise, T temel türleri, T'ün temel arabirimleri ve objectsınıf türüdür.
  • T bir array_typeise, temel T türleri System.Array ve objectsınıf türleridir.
  • T bir delegate_typeise, temel T türleri System.Delegate ve objectsınıf türleridir.

12.6 İşlev üyeleri

12.6.1 Genel

Fonksiyon üyeleri yürütülebilir ifadeler içeren üyelerdir. İşlev üyeleri her zaman türlerin üyesidir ve ad alanlarının üyesi olamaz. C# aşağıdaki işlev üyesi kategorilerini tanımlar:

  • Yöntemler
  • Özellikler
  • Etkinlikler
  • Dizinleyiciler
  • Kullanıcı tanımlı işleçler
  • Nesne oluşturucuları
  • Statik oluşturucular
  • Sonlandırıcılar

Sonlandırıcılar ve statik oluşturucular (açıkça çağrılamaz) dışında, işlev üyelerinde bulunan deyimler işlev üyesi çağrıları aracılığıyla yürütülür. İşlev üyesi çağırması yazmak için gerçek söz dizimi, belirli işlev üyesi kategorisine bağlıdır.

İşlev üyesi çağırmasının bağımsız değişken listesi (§12.6.2), işlev üyesinin parametreleri için gerçek değerler veya değişken referansları sağlar.

Genel yöntemlerin çağrıları, yönteme geçirecek tür argümanları kümesini belirlemek için tür çıkarımını kullanabilir. Bu işlem §12.6.3açıklanmaktadır.

Yöntemlerin, dizin oluşturucuların, işleçlerin ve örnek oluşturucularının çağrıları, çağrılacak işlev üyesi aday kümesinden hangisini belirlemek için aşırı yükleme çözümlemesi kullanır. Bu işlem §12.6.4açıklanmaktadır.

Belirli bir işlev üyesi bağlama zamanında, büyük olasılıkla aşırı yükleme çözümlemesi yoluyla tanımlandığında, işlev üyesini çağırmanın gerçek çalışma zamanı işlemi §12.6.6içinde açıklanmıştır.

Not: Aşağıdaki tabloda, açıkça çağrılabilen altı işlev üyesi kategorisini içeren yapılarda gerçekleşen işlemler özetlenir. Tabloda, e, x, yve value değişken veya değer olarak sınıflandırılan ifadeleri gösterir T tür olarak sınıflandırılan bir ifadeyi gösterir, F bir yöntemin basit adıdır ve P özelliğin basit adıdır.

İnşa etmek Örnek Açıklama
Yöntem çağırma F(x, y) İçeren sınıf veya yapıda F en iyi yöntemi seçmek için aşırı yükleme çözümlemesi uygulanır. Yöntem, (x, y)bağımsız değişken listesiyle çağrılır. yöntemi staticdeğilse, örnek ifadesi this.
T.F(x, y) Sınıf veya yapı Fiçinde en iyi yöntem T'ı seçmek için aşırı yükleme çözümlemesi uygulanır. yöntemi staticdeğilse bağlama zamanı hatası oluşur. Yöntem, (x, y)bağımsız değişken listesiyle çağrılır.
e.F(x, y) aşırı yükleme çözümlemesi, Ftürü tarafından verilen sınıf, yapı veya arabirimde e en iyi yöntemi seçmek için uygulanır. yöntemi staticolduğunda bağlama zamanı hatası oluşur. yöntemi, e örnek ifadesi ve (x, y)bağımsız değişken listesi ile çağrılır.
Özellik erişimi P İçeren sınıf veya yapıda bulunan özellik P'ın alma erişimcisi çağrılır. P yalnızca yazılabilir olduğunda derleme zamanı hatası oluşur. P staticdeğilse, örnek ifadesi thisolur.
P = value İçeren sınıf veya yapı içinde, P özelliğinin set erişimcisi, (value)bağımsız değişken listesiyle çağrılır. Derleme zamanı hatası, P salt okunur olduğunda oluşur. P staticdeğilse, örnek ifadesi thisolur.
T.P Sınıf veya yapı P içindeki T özelliğinin al erişimcisi çağrıldı. P static değilse ya da P sadece yazılabilir ise derleme zamanı hatası oluşur.
T.P = value Özellik P'nin küme erişimcisi, sınıf veya yapı T'de (value)bağımsız değişken listesiyle çağrılır. P static değilse veya P salt okunursa derleme zamanı hatası oluşur.
e.P P türü tarafından verilen sınıf, yapı veya arabirimde E özellik erişimcisi, eörnek ifadesiyle çağrılır. P static olduğunda veya P yalnızca yazılabilir olduğunda bağlama zamanı hatası oluşur.
e.P = value P türü tarafından verilen sınıf, yapı veya arabirimde, örnek ifadesi E ve bağımsız değişken listesi eile özellik (value)'ın set erişimcisi çağrılır. P, static ise veya P salt okunursa bağlama zamanı hatası oluşur.
Etkinlik erişimi E += value Içeren sınıf veya yapıda olay E ekleme erişimcisi çağrılır. E staticdeğilse, örnek ifadesi thisolur.
E -= value İçeren sınıf veya yapıda olay E için remove erişimcisi çağrılır. E staticdeğilse, örnek ifadesi thisolur.
T.E += value Olay E'nın sınıf veya yapı T'deki ekleme erişimcisi çağrılır. E staticdeğilse bağlama zamanı hatası oluşur.
T.E -= value Sınıf veya yapı E içindeki olay T'ın kaldırma erişimcisi çağrıldı. E staticdeğilse bağlama zamanı hatası oluşur.
e.E += value E türü tarafından belirlenen sınıf, yapı veya arabirimdeki E olayının ekleme erişimcisi, eörnek ifadesiyle çağrılır. E staticolduğunda bağlama zamanı hatası oluşur.
e.E -= value E türü tarafından verilen sınıf, yapı veya arabirimdeki E olayının kaldırma erişimcisi, e örnek ifadesiyle çağrılır. E staticolduğunda bağlama zamanı hatası oluşur.
Dizin oluşturucu erişimi e[x, y] Aşırı yükleme çözümlemesi, etürü tarafından verilen sınıfı, yapısı veya arabirimindeki en iyi dizin oluşturucuyu seçmek için uygulanır. Dizin oluşturucunun get erişimcisi, örnek ifadesi e ve bağımsız değişken listesi (x, y)ile çağrılır. Dizin oluşturucu yalnızca yazılabilir olduğunda bağlama zamanı hatası oluşur.
e[x, y] = value Aşırı yükleme çözümlemesi, etürü tarafından verilen sınıfı, yapısı veya arabirimindeki en iyi dizin oluşturucuyu seçmek için uygulanır. Dizinleyicinin set erişimcisi, e örnek ifadesi ve (x, y, value)bağımsız değişken listesi ile çağrılır. Dizin erişimcisi salt okunur olduğunda bağlama zamanı hatası oluşabilir.
İşleç çağırma -x Aşırı yükleme çözümlemesi, x türü tarafından verilen sınıf veya yapının en iyi tekli işleç seçimi için uygulanır. Seçilen işleç, (x)bağımsız değişken listesiyle çağrılır.
x + y Aşırı yükleme çözümlemesi, x ve ytürleri tarafından verilen sınıflarda veya yapılarda en iyi ikili işleci seçmek için uygulanır. Seçilen işleç, (x, y)bağımsız değişken listesiyle çağrılır.
Örnek oluşturucu çağırma new T(x, y) aşırı yükleme çözümlemesi, Tsınıfında veya yapısında en iyi örnek oluşturucuyu seçmek için uygulanır. Örnek oluşturucu, (x, y)bağımsız değişken listesiyle çağrılır.

son notu

12.6.2 Argüman listeleri

12.6.2.1 Genel

Her işlev üyesi ve temsilci çağrısı, fonksiyon üyesinin parametreleri için gerçek değerler veya değişken başvuruları sağlayan bir bağımsız değişken listesi içerir. İşlev üyesi çağrısının bağımsız değişken listesini belirtme söz dizimi, işlev üyesi kategorisine bağlıdır:

  • Örneğin oluşturucular, yöntemler, dizin oluşturucular ve temsilciler için bağımsız değişkenler aşağıda açıklandığı gibi argument_listolarak belirtilir. Dizin oluşturucular için, küme erişimcisini çağırırken, bağımsız değişken listesi ayrıca atama operatörünün sağ operandı olarak belirtilen ifadeyi de içerir.

    Not: Bu ek bağımsız değişken, aşırı yükleme çözümlemesi için değil, yalnızca küme erişimcisi çağrılırken kullanılır. son notu

  • Özellikler için, get erişimcisini çağırırken bağımsız değişken listesi boş olur; set erişimcisini çağırırken ise atama işleminin sağ operandı olarak belirtilen ifadeden oluşur.
  • Olaylar için bağımsız değişken listesi, += veya -= operatörünün sağ operatörü olarak belirtilen ifadeden oluşur.
  • Kullanıcı tanımlı işleçler için, bağımsız değişken listesi, birli işleç için tek bir işlenen ya da ikili işleç için iki işlenenden oluşur.

Özelliklerin (§15.7) ve olayların (§15.8) argümanları her zaman değer parametreleri (§15.6.2.2) olarak geçirilir. Kullanıcı tanımlı işleçlerin (§15.10) bağımsız değişkenleri her zaman değer parametreleri (§15.6.2.2) veya giriş parametreleri (§9.2.8) olarak geçirilir. Dizin oluşturucuların bağımsız değişkenleri (§15.9) her zaman değer parametreleri (§15.6.2.2), giriş parametreleri (§9.2.8) veya parametre dizileri (§15.6.2.4) olarak geçirilir. Bu işlev üyesi kategorileri için çıkış ve başvuru parametreleri desteklenmez.

Örnek oluşturucu, yöntem, dizin oluşturucu veya temsilci çağrısının bağımsız değişkenleri argument_listolarak belirtilir.

argument_list
    : argument (',' argument)*
    ;

argument
    : argument_name? argument_value
    ;

argument_name
    : identifier ':'
    ;

argument_value
    : expression
    | 'in' variable_reference
    | 'ref' variable_reference
    | 'out' variable_reference
    ;

argüman listesi, virgülle ayrılmış bir veya daha fazla argümandanoluşur. Her bir bağımsız değişken, isteğe bağlı bir argument_name ve bir argument_valueardışık olarak içerir. bağımsız değişken, argument_name ileadlı bir bağımsız değişken olarak adlandırılırken, oysa bağımsız değişken, argument_name olmadan, birkonumsal bağımsız değişkendir.

argument_value aşağıdaki formlardan birini alabilir:

  • Bir ifadesi, bağımsız değişkenin bir değer parametresi olarak geçirildiğini veya giriş parametresine dönüştürülüp bu şekilde geçirildiğini belirtir; bu durum (§12.6.4.2) tarafından belirlenir ve (§12.6.2.3)'te açıklanır.
  • Anahtar kelime in, ardından bir variable_reference (§9.5) gelir ve bağımsız değişkenin giriş parametresi olarak geçirildiğini belirtir (§15.6.2.3.2). Bir değişken giriş parametresi olarak geçirilmeden önce kesinlikle atanmalıdır (§9.4).
  • Anahtar kelime ref'ın ardından bir değişken başvurusu (§9.5), bu bağımsız değişkenin bir referans parametresi olarak iletildiğini ifade eder (§15.6.2.3.3). Başvuru parametresi olarak geçirilmeden önce bir değişken kesinlikle atanmalıdır (§9.4).
  • Anahtar sözcük out'ın ardından gelen variable_reference (§9.5), bağımsız değişkenin bir çıkış parametresi olarak geçirildiğini belirtir (§15.6.2.3.4). Değişkenin çıkış parametresi olarak geçirildiği bir işlev üyesi çağrısından sonra bir değişken kesinlikle atanmış olarak kabul edilir (§9.4).

Form, bağımsız değişkenin parametre geçirme modunu belirler: değer, giriş, referans veya çıkış. Ancak, yukarıda belirtildiği gibi, değer geçirme moduna sahip bir argüman, giriş geçirme moduna sahip bir argümana dönüşebilir.

Uçucu bir alanın (§15.5.4) giriş, çıkış veya başvuru parametresi olarak geçirilmesi uyarıya neden olur, çünkü bu alan çağrılan yöntem tarafından uçucu olarak işlenemez.

12.6.2.2 Karşılık gelen parametreler

Bağımsız değişken listesindeki her bağımsız değişken için, çağrılan işlev üyesinde veya temsilcide karşılık gelen bir parametre olmalıdır.

Aşağıda kullanılan parametre listesi aşağıdaki gibi belirlenir:

  • Sınıflarda tanımlanan sanal yöntemler ve dizin oluşturucular için, parametre listesi, ilk olarak alıcının statik türüyle başlanarak ve temel sınıfları arasında arama yapılarak bulunan işlev üyesinin ilk bildiriminden veya geçersiz kılmasından seçilir.
  • Kısmi yöntemler için, kısmi yöntem bildirimini tanımlayan parametre listesi kullanılır.
  • Diğer tüm işlev üyeleri ve temsilciler için kullanılan tek bir parametre listesi vardır.

Bağımsız değişkenin veya parametrenin konumu, bağımsız değişken listesinde veya parametre listesinde kendisinden önceki bağımsız değişkenlerin veya parametrelerin sayısı olarak tanımlanır.

İşlev üyesi bağımsız değişkenleri için karşılık gelen parametreler aşağıdaki gibi oluşturulur:

  • Örnek oluşturucularının, yöntemlerinin, dizin oluşturucularının ve temsilcilerin argument_list bağımsız değişkenleri:
    • Parametre bir parametre dizisi olmadığı ve işlev üyesi genişletilmiş biçiminde çağrılmadığı sürece parametrenin parametre listesinde aynı konumda yer aldığı konumsal bağımsız değişken bu parametreye karşılık gelir.
    • Parametre dizisine sahip bir işlev üyesi, genişletilmiş formuyla çağrıldığında ve parametre dizisinin parametre listesindeki konumunda veya sonrasında gerçekleştiğinde, konumsal argümanı parametre dizisindeki bir öğeye karşılık gelir.
    • Adlandırılmış bağımsız değişken, parametre listesindeki aynı adın parametresine karşılık gelir.
    • Dizin oluşturucular için, set erişimcisini çağırırken, atama operatörünün sağ operandı olarak belirtilen ifade, set erişimcisi tanımının örtük value parametresine karşılık gelir.
  • Özellikler için get erişicisini çağırdığınızda herhangi bir bağımsız değişken yoktur. Atayıcı erişimciyi çağırırken, atama işlecinin sağ operandı olarak belirtilen ifade, atayıcı erişimci bildiriminin örtük değer parametresine karşılık gelir.
  • Kullanıcı tanımlı tekli işleçler (dönüştürmeler dahil), işleç bildiriminin tek parametresine karşılık gelen tek işlenenden oluşur.
  • Kullanıcı tanımlı ikili işleçler için sol işlenen ilk parametreye, sağ işlenen ise işleç bildiriminin ikinci parametresine karşılık gelir.
  • Bir parametre dizisine karşılık gelen veya pozisyon dışı adlandırılmış bir bağımsız değişkenden sonra gelen adsız bir bağımsız değişken, hiçbir parametreyle eşleşmez.

    Not: Bu, void M(bool a = true, bool b = true, bool c = true);M(c: false, valueB);tarafından çağrılmasını önler. İlk bağımsız değişken konum dışında kullanılır (bağımsız değişken ilk konumda kullanılır, ancak c adlı parametre üçüncü konumdadır), bu nedenle aşağıdaki bağımsız değişkenlerin adlandırılmış olması gerekir. Başka bir deyişle, adlandırılmış bağımsız değişkenlerin sondaki olmayan hâllerine yalnızca ad ve konum aynı parametreyi bulma sonucunu verdiğinde izin verilir. son notu

12.6.2.3 Bağımsız değişken listelerinin çalışma zamanı değerlendirmesi

bir işlev üyesi çağrısının çalışma zamanı işlemesi sırasında (§12.6.6), bağımsız değişken listesinin ifadeleri veya değişken başvuruları soldan sağa doğru sırayla aşağıdaki gibi değerlendirilir:

  • Parametrenin aktarım modu değer geçişine ayarlanmışsa, bir değer argümanı için

    • bağımsız değişken ifadesi değerlendirilir ve karşılık gelen parametre türüne örtük dönüştürme (§10.2) gerçekleştirilir. Sonuçta elde edilen değer, işlev üyesi çağırmasında değer parametresinin ilk değeri olur.

    • aksi takdirde parametrenin geçiş modu girdidir. Bağımsız değişken bir değişken başvurusuysa ve bağımsız değişkenin türü ile parametrenin türü arasında bir kimlik dönüştürmesi (§10.2.2) varsa, sonuçta elde edilen depolama konumu, fonksiyon üyesinin çağrılması sırasında parametre tarafından temsil edilen depolama konumu olur. Aksi takdirde, ilgili parametrenin türüyle aynı türde bir depolama konumu oluşturulur. Bağımsız değişken ifadesi değerlendirilir ve karşılık gelen parametre türüne örtük dönüştürme (§10.2) gerçekleştirilir. Sonuçta elde edilen değer bu depolama konumunda depolanır. Bu depolama konumu, işlev üyesi çağırmasında giriş parametresiyle temsil edilir.

      Örnek: Aşağıdaki bildirimler ve yöntem çağrıları göz önünde bulundurulduğunda:

      static void M1(in int p1) { ... }
      int i = 10;
      M1(i);         // i is passed as an input argument
      M1(i + 5);     // transformed to a temporary input argument
      

      M1(i) yöntem çağrısında, i kendisi bir giriş bağımsız değişkeni olarak aktarılır, çünkü değişken olarak sınıflandırılmıştır ve giriş parametresiyle aynı tür int'ye sahiptir. M1(i + 5) yöntem çağrısında adsız bir int değişkeni oluşturulur, bağımsız değişkenin değeriyle başlatılır ve daha sonra giriş bağımsız değişkeni olarak kullanılır. Bkz. §12.6.4.2 ve §12.6.4.4.

      son örnek

  • Giriş, çıkış veya referans bağımsız değişkeni için, değişken referansı değerlendirilir ve sonuçta elde edilen depolama konumu, fonksiyon üyesi çağrısında parametresi tarafından temsil edilen depolama konumu olur. Bir giriş veya başvuru bağımsız değişkeni için, değişken kesinlikle yöntem çağrısının yapıldığı noktada atanmalıdır. Değişken başvurusu dışa aktarılacak bir bağımsız değişken olarak verilmişse veya bir reference_typedizi öğesiyse, dizinin öğe türünün, parametre türüyle aynı olup olmadığını doğrulamak için çalışma zamanında bir denetim gerçekleştirilir. Bu denetim başarısız olursa bir System.ArrayTypeMismatchException atılır.

Not: Bu çalışma zamanı denetimi dizi kovaryans (§17.6) nedeniyle gereklidir. son notu

Örnek: Aşağıdaki kodda

class Test
{
    static void F(ref object x) {...}

    static void Main()
    {
        object[] a = new object[10];
        object[] b = new string[10];
        F(ref a[0]); // Ok
        F(ref b[1]); // ArrayTypeMismatchException
    }
}

F ögesinin ikinci kez çağrılması, System.ArrayTypeMismatchException'in gerçek öğe türü b olduğu ve stringolmadığı için bir object hatasının atılmasına neden olur.

son örnek

Yöntemler, dizin oluşturucular ve örnek oluşturucuları en doğru parametrelerini bir parametre dizisi (§15.6.2.4) olarak bildirebilir. Bu işlev üyeleri, geçerli olan öğeye bağlı olarak normal veya genişletilmiş biçimlerinde çağrılır (§12.6.4.2):

  • Parametre dizisine sahip bir işlev üyesi normal işliğinde çağrıldığında, parametre dizisi için verilen bağımsız değişken, parametre dizisi türüne örtük olarak dönüştürülebilir (§10.2) bir ifade olmalıdır. Bu durumda, parametre dizisi tam olarak bir değer parametresi gibi davranır.
  • Parametre dizisine sahip bir işlev üyesi genişletilmiş biçiminde çağrıldığında, çağırma parametre dizisi için sıfır veya daha fazla konumsal bağımsız değişken belirtmelidir; burada her bağımsız değişken, parametre dizisinin öğe türüne örtük olarak dönüştürülebilir bir ifadedir (§10.2). Bu durumda çağrı, parametre dizisi türünün bağımsız değişken sayısına karşılık gelen uzunluğu olan bir örneği oluşturur, verilen bağımsız değişken değerleriyle dizi örneğinin öğelerini başlatır ve yeni oluşturulan dizi örneğini gerçek bağımsız değişken olarak kullanır.

Bağımsız değişken listesinin ifadeleri her zaman metin sırasına göre değerlendirilir.

Örnek: Bu nedenle, örnek

class Test
{
    static void F(int x, int y = -1, int z = -2) =>
        Console.WriteLine($"x = {x}, y = {y}, z = {z}");

    static void Main()
    {
        int i = 0;
        F(i++, i++, i++);
        F(z: i++, x: i++);
    }
}

çıktıyı üretir

x = 0, y = 1, z = 2
x = 4, y = -1, z = 3

son örnek

Parametre dizisine sahip bir işlev üyesi genişletilmiş biçiminde en az bir genişletilmiş bağımsız değişkenle çağrıldığında, çağrı, genişletilmiş bağımsız değişkenlerin etrafına dizi başlatıcısı (§12.8.17.4) içeren bir dizi oluşturma ifadesi eklenmiş gibi işlenir. Parametre dizisi için bağımsız değişken olmadığında boş bir dizi geçirilir; geçirilen başvurunun yeni ayrılan mı yoksa mevcut bir boş diziye mi yapıldığı belirtilmemiştir.

Örnek: Bildirime göre

void F(int x, int y, params object[] args);

yönteminin genişletilmiş formunun aşağıdaki çağrıları

F(10, 20, 30, 40);
F(10, 20, 1, "hello", 3.0);

tam olarak karşılık gelir

F(10, 20, new object[] { 30, 40 });
F(10, 20, new object[] { 1, "hello", 3.0 });

son örnek

Bir fonksiyon üyesinde, karşılık gelen isteğe bağlı parametrelerle bağımsız değişkenler atlandığında, fonksiyon üyesinin varsayılan argümanları otomatik olarak iletilir. (Bu, yukarıda açıklandığı gibi bir depolama konumu oluşturmayı içerebilir.)

Not: Bunlar her zaman sabit olduğundan, değerlendirmeleri kalan argümanların değerlendirilmesini etkilemez. son notu

12.6.3 Tür çıkarımı

12.6.3.1 Genel

Tür bağımsız değişkenleri belirtilmeden genel bir yöntem çağrıldığında, tür çıkarımı işlemi, çağrı için tür bağımsız değişkenlerini çıkarmayı dener. Tür çıkarımının varlığı, genel bir yöntemi çağırmak için daha kullanışlı bir söz diziminin kullanılmasına olanak tanır ve programcının yedekli tür bilgilerini belirtmekten kaçınmasını sağlar.

Örnek:

class Chooser
{
    static Random rand = new Random();

    public static T Choose<T>(T first, T second) =>
        rand.Next(2) == 0 ? first : second;
}

class A
{
    static void M()
    {
        int i = Chooser.Choose(5, 213); // Calls Choose<int>
        string s = Chooser.Choose("apple", "banana"); // Calls Choose<string>
    }
}

Tür çıkarımı yoluyla, int ve string tür parametreleri, yöntem için verilen bağımsız değişkenlerden belirlenir.

son örnek

Tür çıkarımı, yöntem çağrısının (§12.8.10.2) bağlama zamanı işlemesinin bir parçası olarak gerçekleşir ve çağrının aşırı yükleme çözümleme adımından önce gerçekleşir. Bir yöntem çağrısında belirli bir yöntem grubu belirtildiğinde ve yöntem çağrısının bir parçası olarak hiçbir tür bağımsız değişkeni belirtilmediğinde, yöntem grubundaki her genel yönteme tür çıkarımı uygulanır. Tür çıkarımı başarılı olursa, sonraki aşırı yükleme kararı için argüman türlerini belirlemek amacıyla çıkarsanan tür argümanları kullanılır. Aşırı yük çözümlemesi çağrılacak yöntem olarak bir genel yöntem seçerse, çağrının tür bağımsız değişkenleri olarak çıkarsanan tür bağımsız değişkenleri kullanılır. Belirli bir yöntem için tür çıkarımı başarısız olursa, bu yöntem aşırı yükleme çözümlemeye katılmaz. Tür çıkarımının kendi içinde başarısızlığı, bağlama zamanı hatasına neden olmaz. Ancak, genellikle aşırı yükleme çözümlemesi geçerli yöntemleri bulamayınca bağlama süresi hatasına yol açar.

Sağlanan her bağımsız değişken yöntemdeki (§12.6.2.2) tam olarak bir parametreye karşılık gelmiyorsa veya karşılık gelen bağımsız değişkeni olmayan isteğe bağlı olmayan bir parametre varsa, çıkarım hemen başarısız olur. Aksi takdirde, genel yöntemin aşağıdaki imzaya sahip olduğunu varsayalım:

Tₑ M<X₁...Xᵥ>(T₁ p₁ ... Tₓ pₓ)

M(E₁ ...Eₓ) biçimindeki bir yöntem çağrısında, tür çıkarımı görevi, S₁...Sᵥ çağrısının geçerli hale gelmesi için X₁...Xᵥ tür parametrelerinin her biri için M<S₁...Sᵥ>(E₁...Eₓ) benzersiz tür bağımsız değişkenlerini bulmaktır.

Tür çıkarımı işlemi aşağıda bir algoritma olarak açıklanmıştır. Uyumlu bir derleyici, her durumda aynı sonucta ulaşması koşuluyla alternatif bir yaklaşım kullanılarak uygulanabilir.

Çıkarım işlemi sırasında, her tür parametresi ya belirli bir türe Xᵢ ya da sabitlenmemiştir ve ilişkili bir Sᵢ sahiptir. Sınırların her biri bir türdür . Başlangıçta her tür değişkeni Xᵢ boş bir sınır kümesiyle sabitlenmemiştir.

Tür çıkarımı aşamalar halinde gerçekleşir. Her aşama, önceki aşamanın bulgularına göre daha fazla tip değişkeni için tip argümanlarını türetmeye çalışır. İlk aşama sınırların bazı ilk çıkarımlarını yaparken, ikinci aşama tür değişkenlerini belirli türlere düzeltir ve daha fazla sınır çıkartır. İkinci aşamanın birkaç kez tekrarlanması gerekebilir.

Not: Tür çıkarımı, yöntem gruplarının (§12.6.3.15) dönüştürülmesi ve bir ifade kümesinin en iyi ortak türünü (§12.6.3.16) bulma dahil olmak üzere diğer bağlamlarda da kullanılır. son notu

12.6.3.2 İlk aşama

Yöntem bağımsız değişkenlerinin Eᵢher biri için, öğesinden ilgili parametre türüne bir giriş türü Eᵢçıkarımı (Tⱼ) yapılır.

12.6.3.3 İkinci aşama

İkinci aşama aşağıdaki gibi devam eder:

  • (§12.6.3.6) Xᵢbağımlı olmayan tümdüzeltilmemiş tür değişkenleri Xₑ sabittir (§12.6.3.13).
  • Böyle tür değişkenleri yoksa, tüm aşağıdakilerin geçerli olduğu Xᵢ tür değişkenleri belirlenmiş olur:
    • Xₑ 'ye bağlı en az bir tür değişkeni Xᵢ vardır.
    • Xᵢ boş olmayan bir sınır kümesi var
  • Böyle bir tür değişkeni yoksa ve sabitlenmemiş tür değişkeni varsa tür çıkarımı başarısız olur.
  • Aksi takdirde, daha fazla sabitlenmemiş tür değişkeni yoksa, tür çıkarımı başarılı bir şekilde sonuçlanır.
  • Aksi takdirde, Eᵢ (Tⱼ) sabitlenmemiş tür değişkenleri içerdiği ancak giriş türlerinin (Xₑ) içermediği ilgili parametre türüne sahip tüm bağımsız değişkenler için çıkış türü çıkarımı (§12.6.3.8) öğesindenEᵢTⱼ Ardından ikinci aşama tekrarlanır.

12.6.3.4 Giriş türleri

bir yöntem grubu veya örtük yazılan anonim bir işlevse ve bir temsilci türü veya ifade ağacı türüyse, o zaman 'nin tüm parametre türleri,türüne sahip'nin giriş türleridir.

12.6.3.5 Çıkış türleri

Eğer bir yöntem grubu veya anonim işlevse ve bir temsilci türü veya ifade ağacı türüyse, o zaman dönüş türü,türüne sahipçıkış türüdür.

12.6.3.6 Bağımlılığı

düzeltilmemiş tür değişkeni , türü giriş türü sabitlenmemiş tür değişkeni türüne sahip doğrudan bağlıdır.

Xₑ , XᵢXₑ'ye bağlıysa veya XᵢXᵢ'e bağlıysa ve XᵥXᵥ'e bağlıysaXₑ'e bağlıdır. Bu nedenle, "'e bağımlıdır" ifadesi, "doğrudan'e bağımlıdır" ifadesinin geçişli ama yansıtıcı olmayan kapanışıdır.

12.6.3.7 Giriş türü çıkarımları

Bir giriş türü çıkarımı, bir ifadeden E bir türe T yapılır:

  • E Arity ve öğeleri Nolan bir tanımlama grubu ifadesi (Eᵢ) ise ve T karşılık gelen öğe türlerine N sahip arity Tₑ içeren bir tanımlama grubu türüyse veya T null atanabilir bir değer türüyse T0? ve T0 karşılık gelen öğe türüne sahip bir tanımlama N grubu türüyseTₑ, her Eᵢbiri için giriş türü çıkarımı öğesinden EᵢTₑyapılır.
  • Anonim bir işlevseE, açık parametre türü çıkarımı (§12.6.3.9)ET
  • Aksi takdirde, türü E varsa U ve karşılık gelen parametre bir değer parametresiyse (§15.6.2.2) alt sınır çıkarımı (§12.6.3.11) ileUT
  • Aksi takdirde, türü E varsa U ve karşılık gelen parametre bir başvuru parametresi (§15.6.2.3.3) veya çıkış parametresi (§15.6.2.3.4) ise tam çıkarım (§12.6.3.10) öğesindenUT
  • Aksi takdirde, türü E varsa U ve karşılık gelen parametre bir giriş parametresi (§15.6.2.3.2) ve E bir giriş bağımsız değişkeniyse, tam çıkarım (§12.6.3.10) öğesindenUT
  • Aksi takdirde, türü E varsa U ve karşılık gelen parametre bir giriş parametresiyse (§15.6.2.3.2) alt sınır çıkarımı (§12.6.3.11) öğesindenUT
  • Aksi takdirde, bu bağımsız değişken için çıkarım yapılmaz.

12.6.3.8 Çıkış türü çıkarımları

Bir çıkış türü çıkarımı, aşağıdaki şekilde bir ifadeden bir türe ET yapılır:

  • E arity N ve öğeleri Eᵢolan bir tanımlama grubu ifadesiyse ve T karşılık gelen öğe türlerine N sahip bir tanımlama Tₑ grubu türüyse veya T null atanabilir bir değer türüyse T0? ve T0 karşılık gelen öğe türüne sahip arity N değerine sahip bir tanımlama grubu türüyseTₑ, her Eᵢ bir çıkış türü çıkarımı öğesinden EᵢTₑyapılır.
  • Çıkarsanan dönüş türüne E (U) sahip anonim bir işlevse ve T dönüş türüne Tₓsahip bir temsilci türü veya ifade ağacı türüyse, alt sınır çıkarımı (§12.6.3.11) ileUTₓ
  • Aksi takdirde, bir yöntem grubuysa ve , parametre türleri ve dönüş türü olan bir temsilci türü veya ifade ağacı türüyse ve türleriyle yapılan aşırı yükleme çözümlemesi, dönüş türü olan tek bir yöntem üretiyorsa,'ın'e yapıldığı yerden alt sınır çıkarımı yapılır.
  • Aksi takdirde, türünde bir ifadesiyse,'den'a doğru bir alt sınır çıkarımı yapılır.
  • Aksi takdirde çıkarım yapılmaz.

12.6.3.9 Açık parametre türü çıkarımları

Açık parametre türü çıkarımı bir ifadeden bir türeE aşağıdaki şekilde yapılır:

  • Parametre türleriyle açıkça yazılan bir anonim işlevse EU₁...Uᵥ ve T parametre türlerine V₁...VᵥUᵢ sahip bir temsilci türü veya ifade ağacı türüyse, her biri için tam çıkarım (§12.6.3.10) Uᵢ karşılık gelen Vᵢöğesine yapılır.

12.6.3.10 Tam çıkarımlar

tam çıkarım bir tür U'ten bir tür V'ye şu şekilde yapılır:

  • V sabitlenmemişXᵢ biriyse, Uiçin tam sınır kümesine Xᵢ eklenir.
  • Aksi takdirde, V₁...Vₑ ve U₁...Uₑ kümeleri, aşağıdaki durumlardan birinin geçerli olup olmadığını denetleyerek belirlenir:
    • V bir dizi türü V₁[...] ve U aynı dereceye sahip bir dizi türü U₁[...]
    • V, V₁? türü olup, U ise U₁ türüdür.
    • V, bir yapılandırılmış türdür C<V₁...Vₑ> ve U, bir yapılandırılmış türdür C<U₁...Uₑ>
      Bu durumlardan herhangi biri geçerliyse, her bir 'den ilgili Uᵢ'e kadar Vᵢ yapılır.
  • Aksi takdirde çıkarım yapılmaz.

12.6.3.11 Alt sınır çıkarımları

Bir tür 'den türe olmak üzere tür için alt sınır çıkarımı aşağıdaki gibi yapılır:

  • Eğer V, sabitlenmemişXᵢ’den biri ise, U, Xᵢiçin alt sınırlar kümesine eklenir.
  • Aksi takdirde, V türü V₁? ve U türü U₁? ise, U₁'den V₁'e daha düşük bir sınır çıkarımı yapılır.
  • Aksi takdirde, U₁...Uₑ ve V₁...Vₑ kümeleri, aşağıdaki durumlardan birinin geçerli olup olmadığını denetleyerek belirlenir:
    • V bir dizi türü V₁[...]ve U aynı dereceye sahip bir dizi türü U₁[...]
    • V IEnumerable<V₁>, ICollection<V₁>, IReadOnlyList<V₁>>, IReadOnlyCollection<V₁> veya IList<V₁> biridir ve U tek boyutlu bir dizi türüdür U₁[]
    • V, class, struct, interface veya delegate türü oluşturulmuş bir C<V₁...Vₑ>'tir ve C<U₁...Uₑ>, U (veya, U bir parametertürüyse, etkin temel sınıfı veya etkin arabirim kümesinin herhangi bir üyesi) ile aynı olan, doğrudan veya dolaylı olarak inherits'dan türemiş veya C<U₁...Uₑ>'i uygulayan (doğrudan veya dolaylı olarak) benzersiz bir türdür.
    • ("Benzersizlik" kısıtlaması, C<T>{} class U: C<X>, C<Y>{}U veya C<T>olabileceğinden, U₁'den X'a çıkarılırken Yarabirimde çıkarım yapılmadığı anlamına gelir.)
      Bu durumlardan herhangi biri geçerliyse, her bir Uᵢ'dan ilgili Vᵢ'e aşağıdaki gibi bir çıkarım yapılır:
    • Uᵢ bir başvuru türü olarak bilinmiyorsa tam bir çıkarım yapılır
    • Aksi takdirde, U bir dizi türüyse, için bir alt sınır çıkarımı yapılır.
    • Aksi takdirde, eğer VC<V₁...Vₑ> ise, çıkarım i-th'ün C türü parametresine bağlıdır:
      • Kovaryant ise, alt sınır çıkarımı yapılır.
      • Kontravar ise, üst sınır çıkarımı yapılır.
      • Eğer sabitse, kesin çıkarım yapılır.
  • Aksi takdirde çıkarım yapılmaz.

12.6.3.12 Üst sınır çıkarımları

Bir üst sınır çıkarımı, türünde U olarak aşağıdaki şekilde yapılır:

  • V sabitlenmemişXᵢ biriyse, Uiçin üst sınır kümesine Xᵢ eklenir.
  • Aksi takdirde, V₁...Vₑ ve U₁...Uₑ kümeleri, aşağıdaki durumlardan birinin geçerli olup olmadığını denetleyerek belirlenir:
    • U bir dizi türü U₁[...]ve V aynı dereceye sahip bir dizi türü V₁[...]
    • U IEnumerable<Uₑ>, ICollection<Uₑ>, IReadOnlyList<Uₑ>, IReadOnlyCollection<Uₑ> veya IList<Uₑ> biridir ve V tek boyutlu bir dizi türüdür Vₑ[]
    • U, U1? türü olup, V ise V1? türüdür.
    • U, C<U₁...Uₑ> türündeki bir sınıf, yapı, arayüz veya temsilcidir ve Vclass, struct, interface veya delegate türündedir. Bu tür doğrudan veya dolaylı olarak identical türüne inherits'dir, C<V₁...Vₑ> türünü doğrudan veya dolaylı olarak uygular.
    • ("Benzersizlik" kısıtlaması, C<T>{} class V<Z>: C<X<Z>>, C<Y<Z>>{}bir arabirim verildiğinde, C<U₁>'den V<Q>'ye çıkarım yapılmadığı anlamına gelir. U₁'den X<Q>'e veya Y<Q>'e çıkarım yapılmaz.)
      Bu durumlardan herhangi biri geçerliyse, her bir Uᵢ'dan ilgili Vᵢ'e aşağıdaki gibi bir çıkarım yapılır:
    • Uᵢ bir başvuru türü olarak bilinmiyorsa tam bir çıkarım yapılır
    • Aksi takdirde, V bir dizi türüyse üst sınır çıkarımı yapılır
    • Aksi takdirde, eğer UC<U₁...Uₑ> ise, çıkarım i-th'ün C türü parametresine bağlıdır:
      • Eğer covariant ise, o zaman bir üst sınır çıkarımı yapılır.
      • Değişken karşıtıysa, alt sınır çıkarımı yapılır.
      • Eğer sabitse, kesin çıkarım yapılır.
  • Aksi takdirde çıkarım yapılmaz.

12.6.3.13 Düzeltme

Bir sınır kümesine sahip düzeltilmemiş tür değişkeni Xᵢ aşağıdaki şekilde sabitlenir:

  • Aday türler kümesi, başlangıçta sınırları kümesindeki tüm türlerden oluşur.
  • Xᵢ için her bir sınır sırayla incelenir: Her bir Xᵢ kesin sınırı U için, Uₑ ile özdeş olmayan tüm U türleri aday kümesinden kaldırılır. U'in her alt sınırı Xᵢ için, Uₑ'ten örtük bir dönüşümün olmadığı tüm U türleri aday kümesinden kaldırılır. Xᵢ için her bir üst sınır U olduğunda, Uₑ'e örtük dönüşüm olmadığı için olmayan tüm U türleri aday kümesinden kaldırılır.
  • Kalan aday türleri arasında, diğer tüm aday türlerinden örtük dönüştürmenin olduğu benzersiz bir tür Uₑ varsa, V, Xᵢ olarak sabitlenir.
  • Aksi takdirde tür çıkarımı başarısız olur.

12.6.3.14 Çıkarımlı dönüş türü

Anonim işlev F çıkarımlı dönüş türü, tür çıkarımı ve aşırı yükleme çözümlemesi sırasında kullanılır. Çıkarsanan dönüş türü, yalnızca tüm parametre türlerinin bilindiği anonim bir işlev için belirlenebilir. Bunlar ya açıkça belirtilir, anonim bir işlev dönüşümü ile sağlanır ya da kapsayıcı bir genel yöntem çağrısındaki tür çıkarımı sürecinde belirlenir.

çıkarılan etkin dönüş türü aşağıdaki gibi belirlenir:

  • Eğer F gövdesi bir türü olan ifadesi ise, o zaman F'nin belirlenmiş etkin dönüş türü o ifadenin türüdür.
  • gövdesi F bir bloksa ve bloğun return deyimlerindeki ifade kümesi en iyi ortak türe T (§12.6.3.16) sahipse, çıkarılmış etkin dönüş türü F olur T.
  • Aksi takdirde, Fiçin etkili bir dönüş türü çıkarılamaz.

çıkarımlı dönüş türü aşağıdaki gibi belirlenir:

  • F asenkron ise ve F gövdesi hiçbir şey olarak sınıflandırılmış bir ifade (§12.2) ya da ifadelerin bulunmadığı bir bloksa, çıkarılan dönüş türü return olur («TaskType»).
  • Eğer F asenkron ise ve T çıkarılmış etkin dönüş türüne sahipse, çıkarılmış dönüş türü «TaskType»<T>» (§15.14.1) olur.
  • F uyumsuz değilse ve çıkarılmış etkin dönüş türü T ise, çıkarsanan dönüş türü T olur.
  • Aksi takdirde, Fiçin bir dönüş türü çıkarılamaz.

Örnek: Anonim işlevleri içeren tür çıkarımı örneği olarak, Select sınıfında bildirilen System.Linq.Enumerable uzantısı yöntemini göz önünde bulundurun:

namespace System.Linq
{
    public static class Enumerable
    {
        public static IEnumerable<TResult> Select<TSource,TResult>(
            this IEnumerable<TSource> source,
            Func<TSource,TResult> selector)
        {
            foreach (TSource element in source)
            {
                yield return selector(element);
            }
        }
   }
}

System.Linq ad alanının bir using namespace yönergesi ile içeri aktarıldığı ve Customertüründe Name özelliğine sahip bir sınıf string verildiği varsayıldığında, Select yöntemi bir müşteri listesinin adlarını seçmek için kullanılabilir:

List<Customer> customers = GetCustomerList();
IEnumerable<string> names = customers.Select(c => c.Name);

uzantı yöntemi çağrısı (Select), çağrı statik yöntem çağrısına yeniden yazılarak işlenir:

IEnumerable<string> names = Enumerable.Select(customers, c => c.Name);

Tür bağımsız değişkenleri açıkça belirtilmediğinden tür bağımsız değişkenlerini çıkarsamak için tür çıkarımı kullanılır. İlk olarak, müşteri argümanı kaynak parametresiyle ilişkilidir ve TSource'ın Customerolduğu çıkarımı yapılmaktadır. Ardından, yukarıda açıklanan anonim işlev türü çıkarım işlemi kullanılarak c türü Customerverilir ve c.Name ifadesi seçici parametresinin dönüş türüyle ilişkilendirilerek, TResult'ün stringolduğu çıkarılır. Bu nedenle çağrı şu şekildedir:

Sequence.Select<Customer,string>(customers, (Customer c) => c.Name)

ve sonuç IEnumerable<string>türündedir.

Aşağıdaki örnekte, anonim işlev türü çıkarımının, bir generic metot çağırma sırasında parametreler arasında tür bilgilerinin nasıl "akmasına" izin verdiği gösterilmektedir. Aşağıdaki yöntem ve çağırma göz önünde bulundurulduğunda:

class A
{
    static Z F<X,Y,Z>(X value, Func<X,Y> f1, Func<Y,Z> f2)
    {
        return f2(f1(value));
    }

    static void M()
    {
        double hours = F("1:15:30", s => TimeSpan.Parse(s), t => t.TotalHours);
    }
}

çağırma için tür çıkarımı şu şekilde devam eder: İlk olarak, "1:15:30" bağımsız değişkeni değer parametresiyle ilişkilidir ve bu ilişkiye göre X'ın stringolduğu çıkartılır. Ardından, ilk anonim işlevin parametresi siçin çıkarılan tür stringolarak verilir ve TimeSpan.Parse(s) ifadesi, f1'ün dönüş türü ile ilişkilendirilerek, Y'ün System.TimeSpanolduğu sonucu çıkarılır. Son olarak, ikinci anonim işlevin parametresi t'e, belirlenen tür System.TimeSpanverilir ve t.TotalHours ifadesi, f2dönüş türüyle ilişkilendirilir ve Z'ün doubleolduğu belirlenir. Bu nedenle, çağırmanın sonucu doubletüründedir.

son örnek

12.6.3.15 Yöntem gruplarının dönüştürülmesi için tür çıkarımı

Genel yöntemlerin çağrılarına benzer şekilde, genel bir yöntem içeren bir yöntem grubu M belirli bir temsilci türüne D (§10.8) dönüştürüldüğünde tür çıkarımı da uygulanır. Bir yöntem verildiğinde

Tₑ M<X₁...Xᵥ>(T₁ x₁ ... Tₑ xₑ)

ve yöntem grubu M temsilci türü D olarak atanırken, tür çıkarımı görevi, S₁...Sᵥ tür bağımsız değişkenlerini bulmaktır, bu şekilde ifade:

M<S₁...Sᵥ>

ile uyumlu (D) olur.

Genel yöntem çağrıları için tür çıkarımı algoritmasından farklı olarak, bu durumda yalnızca bağımsız değişken türleri vardır, bağımsız değişken ifadeleri yoktur. Özellikle anonim işlevler yoktur ve bu nedenle birden çok çıkarım aşamasına gerek yoktur.

Bunun yerine, tüm Xᵢonaylanmamış olarak kabul edilir ve her bir bağımsız değişken türünden UₑD bir Tₑ yapılır. Xᵢ herhangi biri için hiçbir sınır bulunamadıysa tür çıkarımı başarısız olur. Aksi takdirde, tüm 'lar, türü çıkarımının sonucu olan karşılık gelen 'e sabitlenmiştir .

12.6.3.16 İfade kümesinin en iyi ortak türünü bulma

Bazı durumlarda, bir ifade kümesi için ortak bir tür çıkarılmalıdır. Özellikle, örtük olarak yazılan dizilerin öğe türleri ve blok gövdeli anonim işlevlerin dönüş türleri bu şekilde bulunur.

E₁...Eᵥ bir ifade kümesi için en iyi ortak tür aşağıdaki gibi belirlenir:

  • Yeni düzeltilmemiş türü değişkeni X kullanıma sunulmuştur.
  • Her ifade Ei için bir çıkış türü çıkarımı (§12.6.3.8) ondan öğesine Xgerçekleştirilir.
  • X mümkünse sabittir (§12.6.3.13) ve sonuçta elde edilen tür en iyi ortak türdür.
  • Aksi takdirde çıkarım başarısız olur.

Not: Sezgisel olarak bu çıkarım, void M<X>(X x₁ ... X xᵥ)'ü bağımsız değişken olarak kullanarak Eᵢ yöntemini çağırmak ve Xsonucunu çıkarmakla eşdeğerdir. son notu

12.6.4 Aşırı yük çözümlemesi

12.6.4.1 Genel

Aşırı yükleme çözümlemesi, belirli bir bağımsız değişken listesi ve bir dizi aday işlev üyesi verildiğinde, en iyi işlev üyesini çağırmak için kullanılan bir bağlama zamanı mekanizmasıdır. Aşırı yükleme çözümlemesi, C# içinde aşağıdaki ayrı bağlamlarda çağrılacak işlev üyesini seçer:

  • çağırma_ifadesi içinde adı geçen bir yöntemin çağrılması (§12.8.10).
  • bir object_creation_expression adlı örnek oluşturucunun çağrılması (§12.8.17.2).
  • Dizin oluşturucu erişimcisini element_access aracılığıyla çağırma (§12.8.12).
  • İfadede referans verilen önceden tanımlanmış veya kullanıcı tanımlı işleci çağırma (§12.4.4 ve §12.4.5).

Bu bağlamların her biri aday işlev üyeleri kümesini ve bağımsız değişkenlerin listesini kendi benzersiz yöntemiyle tanımlar. Örneğin, bir yöntem çağrısı için aday kümesi geçersiz kılma (§12.5) olarak işaretlenen yöntemleri içermez ve türetilmiş bir sınıftaki herhangi bir yöntem uygulanıyorsa (§12.8.10.2) temel sınıftaki yöntemler aday değildir.

Aday işlev üyeleri ve bağımsız değişken listesi belirlendikten sonra, her durumda en iyi işlev üyesinin seçimi aynıdır:

  • Öncelikle, aday işlev üyeleri kümesi, verilen bağımsız değişken listesine göre uygulanabilir olan işlev üyelerine indirilir (§12.6.4.2). Bu azaltılmış küme boşsa, derleme zamanı hatası oluşur.
  • Ardından, uygun aday işlev üyeleri kümesinden en iyi işlev üyesi bulunur. Kümede yalnızca bir işlev üyesi varsa, bu işlev üyesi en iyi işlev üyesidir. Aksi takdirde, her işlev üyesinin §12.6.4.3içindeki kurallar kullanılarak diğer tüm işlev üyeleriyle karşılaştırılması koşuluyla, en iyi işlev üyesi verilen bağımsız değişken listesiyle ilgili olarak diğer tüm işlev üyelerinden daha iyi olan tek işlev üyesidir. Diğer tüm işlev üyelerinden daha iyi olan tam olarak bir işlev üyesi yoksa, işlev üyesi çağrısı belirsizdir ve bağlama zamanı hatası oluşur.

Aşağıdaki alt bildirimler, geçerli işlev üyesi ve daha iyi işlev üyesiterimlerinin tam anlamlarını tanımlar.

12.6.4.2 Uygulanabilir işlev üyesi

Bir işlev üyesinin, bir bağımsız değişken listesine göre olduğu, aşağıdakilerin tümü doğru olduğunda söylenir:

  • A'deki her bağımsız değişken, §12.6.2.2'de açıklandığı gibi işlev üyesi bildirimindeki bir parametreye karşılık gelir. En fazla bir bağımsız değişken her parametreye karşılık gelir ve bağımsız değişkenin karşılık olmadığı tüm parametreler isteğe bağlı bir parametredir.
  • Aiçindeki her bağımsız değişken için bağımsız değişkenin parametre geçirme modu, karşılık gelen parametrenin parametre geçirme moduyla aynıdır ve
    • değer parametresi veya bir parametre dizisi için, bağımsız değişken ifadesinden ilgili parametrenin türüne örtük bir dönüştürme (§10.2) mevcuttur veya
    • başvuru veya çıkış parametresi için, varsa bağımsız değişkenin türü ile karşılık gelen parametrenin türü arasında bir kimlik dönüşümü vardır veya
    • bir giriş parametresi için, karşılık gelen bağımsız değişkene in değiştiricisi uygulandığında, bağımsız değişken ifadesinin türü (varsa) ile karşılık gelen parametrenin türü arasında birebir dönüştürme olur veya
    • bir giriş parametresi için, karşılık gelen bağımsız değişken in değiştiriciyi atladığında, bağımsız değişken ifadesinden ilgili parametrenin türüne örtük bir dönüştürme (§10.2) vardır.

Parametre dizisi içeren bir işlev üyesi için, işlev üyesi yukarıdaki kurallar tarafından uygulanıyorsa,normal formunda geçerli olduğu söylenir. Parametre dizisi içeren bir işlev üyesi normal biçiminde uygulanamazsa, işlev üyesi bunun yerine genişletilmiş formuuygulanabilir:

  • Genişletilmiş form, işlev üyesi bildirimindeki parametre dizisi, parametre dizisinin öğe türündeki sıfır veya daha fazla değer parametresiyle değiştirilerek oluşturulur, böylece bağımsız değişken listesindeki bağımsız değişken sayısı A toplam parametre sayısıyla eşleşir. A, işlev üyesi bildirimindeki sabit parametre sayısından daha az bağımsız değişkene sahipse, işlev üyesinin genişletilmiş biçimi oluşturulamaz ve bu nedenle geçerli değildir.
  • Aksi takdirde, Aiçindeki her bağımsız değişken için aşağıdakilerden biri doğruysa genişletilmiş form geçerlidir:
    • bağımsız değişkenin parametre geçirme modu, karşılık gelen parametrenin parametre geçirme moduyla aynıdır ve:
      • Genişletme tarafından oluşturulan bir sabit değer parametresi veya bir değer parametresi için, bağımsız değişken ifadesinden karşılık gelen parametrenin türüne örtük bir dönüşüm (§10.2) mevcuttur; veya
      • bir başvuru parametresi için bağımsız değişken ifadesinin türü, karşılık gelen parametrenin türüyle aynıdır.
    • Bağımsız değişkenin parametre aktarım modu değer şeklindedir ve karşılık gelen parametrenin aktarım modu ise giriş şekline göredir; bağımsız değişken ifadesinden ilgili parametrenin türüne örtük bir dönüşüm (§10.2) mevcuttur.

Bağımsız değişken türünden bir giriş parametresinin parametre türüne yapılan örtük dönüşüm dinamik bir örtük dönüşüm olduğunda (§10.2.10), sonuçlar belirsizdir.

Örnek: Aşağıdaki bildirimler ve yöntem çağrıları göz önünde bulundurulduğunda:

public static void M1(int p1) { ... }
public static void M1(in int p1) { ... }
public static void M2(in int p1) { ... }
public static void Test()
{
    int i = 10; uint ui = 34U;

    M1(in i);   // M1(in int) is applicable
    M1(in ui);  // no exact type match, so M1(in int) is not applicable
    M1(i);      // M1(int) and M1(in int) are applicable
    M1(i + 5);  // M1(int) and M1(in int) are applicable
    M1(100u);   // no implicit conversion exists, so M1(int) is not applicable

    M2(in i);   // M2(in int) is applicable
    M2(i);      // M2(in int) is applicable
    M2(i + 5);  // M2(in int) is applicable
}

son örnek

  • Statik yöntem yalnızca yöntem grubu bir tür aracılığıyla bir simple_name veya member_access sonucu verirse geçerlidir.
  • Örnek yöntem yalnızca, yöntem grubu bir simple_name, bir değişken veya değer üzerinden member_access ya da base_accesssonucunda oluştuğunda uygulanabilir.
    • Yöntem grubu bir simple_namesonucu verirse, örnek yöntemi yalnızca this erişime izin verildiğinde uygulanabilir §12.8.14.
  • Yöntem grubu, §12.8.7.2açıklandığı gibi bir örnek veya tür aracılığıyla olabilecek bir member_access elde ettiğinde, hem örnek hem de statik yöntemler uygulanabilir.
  • Tür bağımsız değişkenleri (açıkça belirtilen veya çıkarılan) kısıtlamalarını karşılamayan bir genel yöntem geçerli değildir.
  • Yöntem grubu dönüştürme bağlamında, yöntem dönüş türünden temsilcinin dönüş türüne bir kimlik dönüşümü (§10.2.2) veya örtük başvuru dönüşümü (§10.2.8) bulunmalıdır. Aksi takdirde aday yöntemi geçerli değildir.

12.6.4.3 Daha iyi işlev üyesi

Daha iyi işlev üyesini belirlemek amacıyla, yalnızca bağımsız değişken ifadelerinin özgün bağımsız değişken listesinde göründükleri sırayla kendilerini içeren ve A veya out bağımsız değişkenleri dışlayan bir kaldırılmış bağımsız değişken listesi ref oluşturulur.

Aday işlev üyelerinin her biri için parametre listeleri aşağıdaki şekilde oluşturulur:

  • Genişletilmiş form, fonksiyon üyesi ancak genişletilmiş formda uygulanabiliyorsa kullanılır.
  • Karşılık gelen bağımsız değişken içermeyen isteğe bağlı parametreler parametre listesinden kaldırılır
  • Başvuru ve çıkış parametreleri parametre listesinden kaldırılır
  • Parametreler, bağımsız değişken listesindeki karşılık gelen bağımsız değişkenle aynı konumda olacak şekilde yeniden sıralanır.

Bağımsız değişken ifadesi kümesine sahip bir bağımsız değişken listesi A verildiğinde ve parametre türleri {E₁, E₂, ..., Eᵥ} ve Mᵥolan iki geçerli işlev üyesi Mₓ ve {P₁, P₂, ..., Pᵥ} olduğunda, {Q₁, Q₂, ..., Qᵥ}'nın Mᵥ'den daha iyi bir işlev üyesi olarak tanımlanması, şuna bağlıdır.

  • her bağımsız değişken için, Eᵥ'dan Qᵥ'e olan örtük dönüşüm, Eᵥ'den Pᵥ'e olan örtük dönüşümden daha iyi değildir ve
  • en az bir argüman için, Eᵥ'dan Pᵥ'e dönüşüm, Eᵥ'den Qᵥ'e dönüşümden daha iyidir.

parametre türü dizileri {P₁, P₂, ..., Pᵥ} ve {Q₁, Q₂, ..., Qᵥ} eşdeğerse (yani, her Pᵢ'nin karşılık gelen Qᵢ'e bir kimlik dönüşümü varsa), daha iyi işlev üyesini belirlemek için sırasıyla aşağıdaki bağlama kırma kuralları uygulanır.

  • Mᵢ genel olmayan bir yöntemse ve Mₑ genel bir yöntemse, MᵢMₑ'den daha iyidir.
  • Aksi takdirde, Mᵢ normal biçiminde uygulanıyorsa ve Mₑ bir params dizisi varsa ve yalnızca genişletilmiş biçiminde uygulanıyorsa, MᵢMₑdaha iyidir.
  • Aksi takdirde, her iki yöntemde de params dizileri varsa ve yalnızca genişletilmiş formlarında uygulanıyorsa ve Mᵢ params dizisinde Mₑparams dizisinden daha az öğe varsa, MᵢMₑdaha iyidir.
  • Aksi takdirde, MᵥMₓ'den daha belirli parametre türlerine sahipse, MᵥMₓ'den daha iyidir. {R1, R2, ..., Rn} ve {S1, S2, ..., Sn}, Mᵥ ve Mₓ'nin belirtilmemiş ve genişletilmemiş parametre türlerini temsil eder. Mᵥparametre türleri, her parametre için MₓRx'den daha az özel değilse Sx'den daha belirgindir ve en az bir parametre için RxSx'den daha belirgindir:
    • Tür parametresi, tür olmayan bir parametreden daha az özeldir.
    • Özyinelemeli bir şekilde, en az bir tür bağımsız değişkeni daha özelse ve hiçbir tür bağımsız değişkeni diğerinde karşılık gelen bağımsız değişkeninden daha az özel olmadığı sürece, bir yapılandırılmış tür, aynı sayıda tür bağımsız değişkeni olan bir başka yapılandırılmış türe göre daha özeldir.
    • Birincinin öğe türü ikincinin öğe türünden daha özelse, dizi türü başka bir dizi türünden (aynı sayıda boyuta sahip) daha belirgindir.
  • Aksi takdirde, bir üye kaldırılmamış bir operatör ve diğeri yükseltilmiş bir operatör ise, kaldırılmamış olan daha iyidir.
  • İşlev üyesinin hiçbiri daha iyi bulunamadıysa ve Mᵥ tüm parametreleri karşılık gelen bir bağımsız değişkene sahipse, varsayılan bağımsız değişkenlerin Mₓ'de en az bir isteğe bağlı parametreyle değiştirilmesi gerekiyorsa, MᵥMₓ'den daha iyidir.
  • En az bir parametre için Mᵥdaha iyi parametre geçirme seçeneği (§12.6.4.4) Mₓ'daki ilgili parametreden daha iyiyse ve Mₓ'daki parametrelerin hiçbiri Mᵥ'den daha iyi parametre geçirme seçeneğini kullanmıyorsa MᵥMₓ'den iyidir.
  • Aksi takdirde, hiçbir işlev üyesi daha iyi değildir.

12.6.4.4 Daha iyi parametre geçirme modu

İki parametreden birinin değer geçirme moduna sahip olması koşuluyla, iki aşırı yüklenmiş yöntemde karşılık gelen parametrelerin yalnızca parametre geçirme moduna göre farklılık göstermesine izin verilir:

public static void M1(int p1) { ... }
public static void M1(in int p1) { ... }

Verilen int i = 10;, §12.6.4.2'ye göre, yapılan çağrılar M1(i) ve M1(i + 5) her iki aşırı yüklemenin de geçerli olmasına neden olur. Bu gibi durumlarda, değere göre parametre geçirme modunu kullanan yöntem, parametre geçirme modu seçiminden daha iyi birtercihtir.

Not: Girdi, çıktı veya referans geçiş modlarının argümanları için böyle bir seçim olması gerekmez, çünkü bu argümanlar yalnızca tam olarak aynı parametre geçiş modlarıyla eşleşir. son notu

12.6.4.5 İfadeden daha iyi dönüştürme

Varsayılan bir örtük dönüştürme C₁'nın bir ifadeden E'e tür T₁'ye dönüştürdüğü ve bir örtük dönüştürme C₂'nin bir ifadeden E'e tür T₂'e dönüştürdüğü göz önüne alındığında, aşağıdaki durumlardan biri geçerli olduğu takdirde, C₁bir dönüştürme olarak C₂'dan daha iyi kabul edilir:

  • E T₁ tam olarak eşleşir ve ET₂ tam olarak eşleşmez (§12.6.4.6)
  • E, ya hem T₁ hem de T₂ile tam olarak eşleşir ya da hiçbiriyle eşleşmez ve T₁, T₂'ten daha iyi bir dönüşüm hedefidir (§12.6.4.7)
  • Ebir yöntem grubudur (§12.2), T₁ dönüştürme için yöntem grubundan tek en iyi yöntemle uyumludur (§21.4) ve C₁ dönüştürme T₂için yöntem grubundan tek en iyi yöntemle uyumlu değildirC₂

12.6.4.6 Tam olarak eşleşen ifade

Verilen bir ifade E ve tür Tile, Eaşağıdaki koşullardan biri sağlanıyorsaT tam olarak eşleşir:

  • E Stürüne sahiptir ve S'den T'e bir kimlik dönüşümü vardır
  • E anonim bir işlevdir, TD temsilci türü veya Expression<D> ifade ağacı türüdür ve aşağıdakilerden biridir:
    • parametre listesi X (E) bağlamında için D bir çıkarsanan dönüş türü vardır ve 'den X dönüş türüne bir kimlik dönüştürmesi vardırD
    • E, dönüş değeri olmayan bir async lambdadır ve D genel olmayan bir «TaskType» dönüş türüne sahiptir
    • Ya E senkron değildir ve D dönüş türüne Y sahiptir ya da E asenkron olup D dönüş türüne «TaskType»<Y>(§15.14.1) sahiptir ve aşağıdakilerden biri geçerlidir:
      • E içeriği, Y ile tam olarak eşleşen bir ifadedir
      • E gövdesi, her return deyiminin Y ile aynı olan bir ifade döndürdüğü bir bloktur.

12.6.4.7 Daha iyi dönüştürme hedefi

Verilen iki tür T₁ ve T₂olduğunda, aşağıdaki koşullardan birine sahipse, T₁, 'den daha iyi bir dönüştürme hedefi olarak kabul edilir.

  • T₁'dan T₂'ye örtük dönüştürme mevcut ve T₂'dan T₁'e örtük dönüştürme yok
  • T₁ is «TaskType»<S₁>(§15.14.1), T₂ is «TaskType»<S₂>, ve S₁, S₂'den daha iyi bir dönüştürme hedefidir.
  • T₁ olur «TaskType»<S₁>(§15.14.1), T₂ olur «TaskType»<S₂> ve T₁ daha uzman T₂
  • T₁, S₁'ün imzalı bir tam sayı türü olduğu durunda S₁? veya S₁'dir ve T₂, S₂'nin işaretsiz bir integral türü olduğu durumda S₂? veya S₂'dır. Özellikle:
    • S₁ sbyte ve S₂byte, ushort, uintveya ulong
    • S₁ short ve S₂ushortveya uintya da ulong
    • S₁ int ve S₂uintveya ulong
    • S₁ long'dır ve S₂ulong'dür

12.6.4.8 Genel sınıflarda aşırı yükleme

Not: Bildirildiği haliyle imzalar benzersiz (§8.6) olsa da, türü bağımsız değişkenlerin yerine koyulması, aynı imzalarla sonuçlanabilir. Böyle bir durumda, aşırı yükleme çözümlemesi, özgün imzaların (tür bağımsız değişkenlerinin değiştirilmesinden önce) varsa en belirli olanını (§12.6.4.3) seçer, aksi takdirde bir hata bildirir. son notu

Örnek: Aşağıdaki örneklerde, bu kurala göre geçerli ve geçersiz olan aşırı yüklemeler gösterilmektedir:

public interface I1<T> { ... }
public interface I2<T> { ... }

public abstract class G1<U>
{
    public abstract int F1(U u);           // Overload resolution for G<int>.F1
    public abstract int F1(int i);         // will pick non-generic

    public abstract void F2(I1<U> a);      // Valid overload
    public abstract void F2(I2<U> a);
}

abstract class G2<U,V>
{
    public abstract void F3(U u, V v);     // Valid, but overload resolution for
    public abstract void F3(V v, U u);     // G2<int,int>.F3 will fail

    public abstract void F4(U u, I1<V> v); // Valid, but overload resolution for
    public abstract void F4(I1<V> v, U u); // G2<I1<int>,int>.F4 will fail

    public abstract void F5(U u1, I1<V> v2);   // Valid overload
    public abstract void F5(V v1, U u2);

    public abstract void F6(ref U u);      // Valid overload
    public abstract void F6(out V v);
}

son örnek

12.6.5 Dinamik üye çağrısının derleme zamanı denetimi

Dinamik olarak bağlı bir işlemin aşırı yükleme çözümlemesi çalışma zamanında gerçekleşse de, bazen derleme zamanında aşırı yüklemenin seçileceği işlev üyeleri listesini bilmek mümkündür:

  • Temsilci çağrısı için (§12.8.10.4), liste, çağrının delegate_type aynı parametre listesine sahip tek bir işlev üyesidir
  • Bir türdeki veya statik türü dinamik olmayan bir değerdeki yöntem çağrısı (§12.8.10.2) için, yöntem grubundaki erişilebilir yöntemler kümesi derleme zamanında bilinir.
  • Nesne oluşturma ifadesi (§12.8.17.2) için, türdeki erişilebilir oluşturucular kümesi derleme zamanında bilinir.
  • Dizin oluşturucu erişimi (§12.8.12.4) için, alıcıdaki erişilebilir dizin oluşturucular kümesi derleme zamanında bilinir.

Bu gibi durumlarda, bilinen işlev üyeleri kümesindeki her bir üyede, çalışma zamanında asla çağrılmayacağının kesin olarak bilinebileceğini görmek için sınırlı bir derleme zamanı kontrolü yapılır. F fonksiyon üyesi için her biri bir değiştirilmiş parametre ve bağımsız değişken listesi oluşturulur.

  • İlk olarak, F genel bir yöntem ise ve tür bağımsız değişkenleri sağlanmışsa, bunlar parametre listesindeki tür parametrelerinin yerine kullanılır. Ancak, tür bağımsız değişkenleri sağlanmadığında, böyle bir değiştirme gerçekleşmez.
  • Ardından, türü açık olan (yani, bir tür parametresi içeren; bkz §8.4.3) herhangi bir parametre ve ilgili bağımsız değişkenler elenir.

F'ın kontrolden geçmesi için aşağıdakilerin tümü geçerli olmalıdır:

  • F için değiştirilen parametre listesi, değiştirilen bağımsız değişken listesi için §12.6.4.2açısından geçerlidir.
  • Değiştirilen parametre listesindeki tüm yapı türleri kısıtlamalarını karşılar (§8.4.5).
  • Yukarıdaki adımda F tür parametreleri değiştirildiyse, kısıtlamaları karşılanmıştır.
  • F statik bir yöntemse, yöntem grubu, alıcısı derleme zamanında değişken veya değer olarak bilinen bir member_access sonucu vermemiş olmalıdır.
  • F bir örnek metot ise, metot grubu, alıcısı derleme zamanında bir tür olarak bilinen bir member_access sonucu meydana gelmemiş olmalıdır.

Hiçbir aday bu testi geçmezse derleme zamanı hatası oluşur.

12.6.6 İşlev üyesi çağırma

12.6.6.1 Genel

Bu alt bölüm, belirli bir işlev üyesini çağırmak için çalışma zamanında gerçekleşen işlemi açıklar. Bağlanma zamanı sürecinin, büyük olasılıkla bir aday fonksiyon üyeleri kümesine aşırı yükleme çözümü uygulayarak çağrılacak belirli bir üyeyi belirlediği varsayılır.

çağırma işlemini açıklama amacıyla işlev üyeleri iki kategoriye ayrılır:

  • Statik işlev üyeleri. Bunlar statik yöntemler, statik özellik erişimcileri ve kullanıcı tanımlı işleçlerdir. Statik işlev üyeleri her zaman sanal değildir.
  • Örnek fonksiyon üyeleri Bunlar örnek yöntemleri, örnek oluşturucuları, örnek özellik erişimcileri ve dizin oluşturucu erişimcileridir. Örnek işlev üyeleri ya sanal değildir ya da sanaldır ve her zaman belirli bir örnekte çalıştırılır. Nesne bir örnek ifadesiyle hesaplanır ve işlev üyesi içinde this (§12.8.14) olarak erişilebilir olur. Örnek oluşturucu için örnek ifadesi yeni ayrılan nesne olarak alınır.

İşlev üyesi çağırmanın çalışma zamanı işlemesi aşağıdaki adımlardan oluşur; burada M işlev üyesidir ve M örnek üyesiyse E örnek ifadesidir:

  • Statik işlev üyesiyse M :
    • Bağımsız değişken listesi, §12.6.2'de açıklandığı şekilde değerlendirilir.
    • M çağrılır.
  • Aksi takdirde, türü E bir değer türündeyse Vve M içinde Vbildirilir veya geçersiz kılınırsa:
    • E değerlendirilir. Bu değerlendirme bir özel duruma neden olursa, başka bir adım yürütülmez. Örnek oluşturucu için bu değerlendirme, yeni nesne için depolama ayırmadan (genellikle yürütme yığınından) oluşur. Bu durumda E bir değişken olarak sınıflandırılır.
    • Değişken olarak sınıflandırılmamışsa EV veya salt okunur bir yapı türü değilse (§16.2.2) ve M salt okunur işlev üyesi değilse (§16.4.12) ve E şunlardan biridir:
      • bir giriş parametresi (§15.6.2.3.2) veya
      • bir readonly alanı (§15.5.3) veya
      • bir readonly başvuru değişkeni veya dönüş (§9.7), ardından türündeki Egeçici bir yerel değişken oluşturulur ve değeri E bu değişkene atanır. E daha sonra bu geçici yerel değişkene başvuru olarak yeniden sınıflandırılmış olur. Geçici değişkene thisiçinde M olarak erişilebilir ancak başka bir şekilde erişilemez. Bu nedenle, yalnızca E yazılabilirse, çağıranın M'nin thisyaptığı değişiklikleri gözlemlesi mümkündür.
    • Bağımsız değişken listesi, §12.6.2'de açıklandığı şekilde değerlendirilir.
    • M çağrılır. E tarafından referans verilen değişken, thistarafından referans verilen değişken olur.
  • Yoksa:
    • E değerlendirilir. Bu değerlendirme bir özel duruma neden olursa, başka bir adım yürütülmez.
    • Bağımsız değişken listesi, §12.6.2'de açıklandığı şekilde değerlendirilir.
    • E türü bir value_typeise, 'i bir E'e dönüştürmek için bir boxing dönüşümü (§10.2.9) yapılır ve E, aşağıdaki adımlarda bu class_type olarak kabul edilir. value_type bir enum_typeise, class_typeSystem.Enum;'dur, yoksa System.ValueType'dur.
    • E değeri geçerli olup olmadığı kontrol edilir. E değeri null ise, bir System.NullReferenceException fırlatılır ve başka adım yürütülmez.
    • Çağrılacak işlev üyesi uygulaması belirlenir:
      • E bağlama zamanı türü bir arabirimse, çağrılması gereken işlev üyesi, M'nin başvurduğu örneğin çalışma zamanı türü tarafından sağlanan E'in uygulamasıdır. Bu işlev üyesi, tarafından başvuruda bulunılan örneğin çalışma zamanı türü tarafından sağlanan uygulamasını belirlemek için arabirim eşleme kuralları (M) uygulanarak Ebelirlenir.
      • Aksi takdirde, M bir sanal işlev üyesiyse, çağrılacak işlev üyesi, Mtarafından başvurulan örneğin çalışma zamanı türü tarafından sağlanan E uygulamasıdır. Bu işlev üyesi, tarafından başvuruda bulunılan örneğin çalışma zamanı türüne göre M en çok türetilmiş uygulamasını (E) belirleme kuralları uygulanarak belirlenir.
      • Aksi takdirde, M sanal olmayan bir işlev üyesidir ve çağıracak işlev üyesi M kendisidir.
    • Yukarıdaki adımda belirlenen işlev üyesi uygulaması çağrılır. E tarafından başvurulan nesne, bu nesneye başvurulan nesne olur.

Not:§12.2, erişimci veya get erişimci olmak üzere ilgili işlev üyesini set çağırmak için özellik erişimini sınıflandırır. Bu erişimciyi çağırmak için yukarıdaki işlem izlenir. son notu

Bir örnek oluşturucusunun (§12.8.17.2) çağrılmasının sonucu, oluşturulan değerdir. Herhangi başka bir işlev üyesinin çağrılmasının sonucu, varsa, gövdesinden döndürülen (§13.10.5) değerdir.

12.6.6.2 Kutulu Örneklerde Çağrılar

Bir value_type içinde uygulanmış işlev üyesi, aşağıdaki durumlarda bu value_type'nin kutulu bir örneği aracılığıyla çağrılabilir:

  • İşlev üyesi, class_type türünden devralınan bir yöntemin geçersiz kılınması olduğunda ve class_typeörnek alma ifadesi aracılığıyla çağrıldığında.

    Not: class_type her zaman System.Object, System.ValueType veya System.Enumbiri olacak.  son notu

  • İşlev üyesi, bir arabirim işlev üyesinin uygulaması olduğunda ve bir arabirim_türüörnek ifadesi aracılığıyla çağrıldığında.
  • İşlev üyesi bir temsilci aracılığıyla çağrıldığında.

Bu gibi durumlarda, kutulu örneğin value_typedeğişkeni içerdiği kabul edilir ve bu değişken işlev üyesi çağırması içinde bunun başvuruda bulunduğu değişken olur.

Not: Bu, özellikle kutulu örnekte bir işlev üyesi çağrıldığında işlev üyesinin kutulu örnekte bulunan değeri değiştirmesinin mümkün olduğu anlamına gelir. son notu

12.7 Yapısızlaştırma

Yapısöküm, bir ifadenin tek tek ifadelerden oluşan bir diziye dönüştürüldüğü bir işlemdir. Yapısızlaştırma, basit bir atamanın hedefi bir tanımlama grubu ifadesi olduğunda, bu tanımlama grubunun öğelerinin her birine atanacak değerleri elde etmek için kullanılır.

İfade , aşağıdaki şekilde içinde öğe bulunan bir demet ifadesine parçalanır.

  • Eğer E, n öğeleri olan bir tanımlama grubu ifadesiyse, yapısızlaştırmanın sonucu E ifadesinin kendisidir.
  • Aksi takdirde, E'ın (T1, ..., Tn) öğesi olan bir tanımlama grubu türü n varsa, o zaman E, __volarak bir geçici değişkene değerlendirilir ve yapısızlaştırmanın sonucu (__v.Item1, ..., __v.Itemn)ifadesi olur.
  • Aksi takdirde, E.Deconstruct(out var __v1, ..., out var __vn) ifadesi derleme zamanında benzersiz bir örneğe veya uzantı yöntemine çözümleniyorsa, bu ifade değerlendirilir ve parçalamanın sonucu (__v1, ..., __vn) ifadesidir. Böyle bir yöntem bir yıkıcı olarak adlandırılır.
  • Aksi takdirde, E sökülemez.

Burada __v ve __v1, ..., __vn görünmez ve erişilemez geçici değişkenlere başvurur.

Not: dynamic türünde bir ifade açıklanamaz. son notu

12.8 Birincil ifadeler

12.8.1 Genel

Birincil ifadeler en basit ifade biçimlerini içerir.

primary_expression
    : literal
    | interpolated_string_expression
    | simple_name
    | parenthesized_expression
    | tuple_expression
    | member_access
    | null_conditional_member_access
    | invocation_expression
    | element_access
    | null_conditional_element_access
    | this_access
    | base_access
    | post_increment_expression
    | post_decrement_expression
    | null_forgiving_expression
    | array_creation_expression
    | object_creation_expression
    | delegate_creation_expression
    | anonymous_object_creation_expression
    | typeof_expression
    | sizeof_expression
    | checked_expression
    | unchecked_expression
    | default_value_expression
    | nameof_expression    
    | anonymous_method_expression
    | pointer_member_access     // unsafe code support
    | pointer_element_access    // unsafe code support
    | stackalloc_expression
    ;

Standart teknikler, karşılıklı sol özyinelemeyi kaldırmak için grameri dönüştürmekte kullanılabilir. Bu Standart, tüm ayrıştırma stratejilerinin bunu gerektirmemesinden dolayı (örneğin, bir LALR ayrıştırıcısının gerektirmemesi) ve bu şekilde yapmak yapıyı ve tanımı bulanıklaştıracağı için bunu yapmaz. son notu

pointer_member_access (§24.6.3) ve pointer_element_access (§24.6.4) yalnızca güvenli olmayan kodda (§24) kullanılabilir.

12.8.2 Değişmez Değerler

Bir değişmez (§6.4.5) içeren bir birincil ifade bir değer olarak sınıflandırılır.

12.8.3 İç İçe Dize İfadeleri

Bir interpolated_string_expression, $, $@veya @$'ten oluşur ve hemen ardından " karakterleri içindeki metin gelir. Alıntılanan metin içinde, her biri bir ifadeyi ve isteğe bağlı biçimlendirme belirtimlerini kapsayan ve { karakterleriyle sınırlanmış sıfır veya daha fazla } bulunur.

İlişkili dize ifadelerinin iki biçimi vardır: regular (interpolated_regular_string_expression) ve verbatim (interpolated_verbatim_string_expression); bunlar, dize değişmezleri iki biçimine (§6.4.5.6) sözcük bakımından benzer, ancak anlamsal olarak farklıdır.

interpolated_string_expression
    : interpolated_regular_string_expression
    | interpolated_verbatim_string_expression
    ;

// interpolated regular string expressions

interpolated_regular_string_expression
    : Interpolated_Regular_String_Start Interpolated_Regular_String_Mid?
      ('{' regular_interpolation '}' Interpolated_Regular_String_Mid?)*
      Interpolated_Regular_String_End
    ;

regular_interpolation
    : expression (',' interpolation_minimum_width)?
      Regular_Interpolation_Format?
    ;

interpolation_minimum_width
    : constant_expression
    ;

Interpolated_Regular_String_Start
    : '$"'
    ;

// the following three lexical rules are context sensitive, see details below

Interpolated_Regular_String_Mid
    : Interpolated_Regular_String_Element+
    ;

Regular_Interpolation_Format
    : ':' Interpolated_Regular_String_Element+
    ;

Interpolated_Regular_String_End
    : '"'
    ;

fragment Interpolated_Regular_String_Element
    : Interpolated_Regular_String_Character
    | Simple_Escape_Sequence
    | Hexadecimal_Escape_Sequence
    | Unicode_Escape_Sequence
    | Open_Brace_Escape_Sequence
    | Close_Brace_Escape_Sequence
    ;

fragment Interpolated_Regular_String_Character
    // Any character except " (U+0022), \\ (U+005C),
    // { (U+007B), } (U+007D), and New_Line_Character.
    : ~["\\{}\u000D\u000A\u0085\u2028\u2029]
    ;

// interpolated verbatim string expressions

interpolated_verbatim_string_expression
    : Interpolated_Verbatim_String_Start Interpolated_Verbatim_String_Mid?
      ('{' verbatim_interpolation '}' Interpolated_Verbatim_String_Mid?)*
      Interpolated_Verbatim_String_End
    ;

verbatim_interpolation
    : expression (',' interpolation_minimum_width)?
      Verbatim_Interpolation_Format?
    ;

Interpolated_Verbatim_String_Start
    : '$@"'
    | '@$"'
    ;

// the following three lexical rules are context sensitive, see details below

Interpolated_Verbatim_String_Mid
    : Interpolated_Verbatim_String_Element+
    ;

Verbatim_Interpolation_Format
    : ':' Interpolated_Verbatim_String_Element+
    ;

Interpolated_Verbatim_String_End
    : '"'
    ;

fragment Interpolated_Verbatim_String_Element
    : Interpolated_Verbatim_String_Character
    | Quote_Escape_Sequence
    | Open_Brace_Escape_Sequence
    | Close_Brace_Escape_Sequence
    ;

fragment Interpolated_Verbatim_String_Character
    : ~["{}]    // Any character except " (U+0022), { (U+007B) and } (U+007D)
    ;

// lexical fragments used by both regular and verbatim interpolated strings

fragment Open_Brace_Escape_Sequence
    : '{{'
    ;

fragment Close_Brace_Escape_Sequence
    : '}}'
    ;

Yukarıda tanımlanan sözcük temelli kuralların altısı bağlama duyarlı aşağıdaki gibidir:

Kuralı Bağlamsal Gereksinimler
İnterpolasyonlu_Düzenli_Dize_Ortası Yalnızca bir Interpolated_Regular_String_Startsonrasında, takip eden interpolasyonlar arasında ve karşılık gelen Interpolated_Regular_String_Endöncesinde tanınır.
Regular_Interpolation_Format Yalnızca bir regular_interpolation içinde ve başlangıç iki nokta üst üste (:) herhangi bir köşeli ayraç (parantez/ayraç/kare) içinde iç içe yerleştirilmediğinde tanınır.
İç içe Geçirilmiş Düzenli Dize Sonu Yalnızca bir Interpolated_Regular_String_Start'den sonra ve araya giren belirteçlerin herhangi birisi Interpolated_Regular_String_Midveya regular_interpolationparçası olabilecek belirteçler olduğunda tanınabilir. Bu, bu tür interpolasyonlar içinde yer alan interpolated_regular_string_expressionbelirteçlerini de kapsar.
Interpolated_Verbatim_String_MidVerbatim_Interpolation_FormatInterpolated_Verbatim_String_End Bu üç kuralın kabul edilmesi, yukarıda belirtilen kuralların her birinin, belirtilen normal dil bilgisi kuralının yerine, ilgili sözel kural ile değiştirildiği şekilde gerçekleşir.

Not: Yukarıdaki kurallar, tanımları dildeki diğer belirteçlerle çakıştığı için bağlama duyarlıdır. son notu

Not: Bağlama duyarlı sözcük kuralları nedeniyle yukarıdaki dil bilgisi ANTLR'ye hazır değildir. Diğer sözcük oluşturucularda olduğu gibi ANTLR, örneğin sözcük temelli modlarınıkullanarak bağlama duyarlı sözcük temelli kuralları destekler, ancak bu bir uygulama ayrıntısıdır ve bu nedenle bu belirtimin bir parçası değildir. son notu

interpolated_string_expression bir değer olarak sınıflandırılır. Örtük bir ara dizgi dönüştürmesi (System.IFormattable) ile hemen System.FormattableString veya 'e dönüştürülürse, ara dizgi ifadesi o türe sahiptir. Aksi takdirde, string türüne sahiptir.

Not: interpolated_string_expression ifadesinin olası türleri arasındaki farklar, System.String (§C.2) ve System.FormattableString (§C.3) belgelerinden belirlenebilir. son notu

hem regular_interpolation hem de verbatim_interpolation ilişkilendirmenin anlamı, Regular_Interpolation_Format veya Verbatim_Interpolation_Format tarafından belirtilen biçime veya ifade türü için varsayılan biçime göre olarak ifadesinin değerini biçimlendirmektir. Biçimlendirilmiş dize, eğer varsa interpolation_minimum_widthtarafından değiştirilerek stringiçine yerleştirilmek üzere son haliyle 'yi oluşturur.

Not: Bir tür için varsayılan biçimin nasıl belirlendiği System.String (§C.2) ve System.FormattableString (§C.3) belgelerinde ayrıntılı olarak açıklanmıştır. Regular_Interpolation_Format ve Verbatim_Interpolation_Formatiçin aynı olan standart biçimlerin açıklamaları, System.IFormattable belgelerinde (§C.4) ve standart kitaplıktaki diğer türlerde (§C) bulunabilir. son notu

Bir interpolation_minimum_width içinde, constant_expression , örtük bir dönüşümle int'e dönüştürülecektir. bu sabit_ifade mutlak değeri alan genişliği ve bu sabit_ifadedeğerinin işareti (pozitif veya negatif) olan hizalama olsun:

  • Alan genişliği değeri, biçimlendirilmiş dizenin uzunluğuna eşit veya ondan küçükse, biçimlendirilmiş dize değiştirilmez.
  • Aksi takdirde biçimlendirilmiş dize, uzunluğu alan genişliğine eşit olacak şekilde boşluk karakterleriyle doldurulur:
    • Eğer hizalama pozitifse, biçimlendirilmiş dize, doldurma ön eklenerek sağa hizalanır.
    • Aksi takdirde, boşluk eklenerek sola hizalama yapılır.

Bir interpolated_string_expression'nin genel anlamı, yukarıdaki biçimlendirme ve yerleştirilen interpolasyonların dolguları da dahil olarak, ifadenin bir yöntem çağrısına dönüştürülmesiyle tanımlanır: ifadenin türü System.IFormattable veya System.FormattableString ise, yöntem System.Runtime.CompilerServices.FormattableStringFactory.Create olur (§C.3) ve System.FormattableStringtüründe bir değer döndürür; aksi takdirde tür string olur ve yöntem string.Format (§C.2) stringtüründe bir değer döndürür.

Her iki durumda da, çağrının bağımsız değişken listesi, her araya yerleştirme için biçim belirtimi içeren bir biçim dizesi değişmez değeri ve biçim belirtimlerine karşılık gelen her ifade için bir bağımsız değişkenden oluşur.

Biçim dizesi değişmez değeri aşağıdaki gibi oluşturulur; burada N, iç içe geçmiş dize ifadesiiçindeki interpolasyonların sayısıdır. Biçim dizesi sabiti, sırasıyla şunlardan oluşur:

  • Interpolated_Regular_String_Start veya Interpolated_Verbatim_String_Start karakterleri
  • Interpolated_Regular_String_Mid veya Interpolated_Verbatim_String_Mid karakterleri, varsa
  • Ardından, N ≥ 1'dan I'e kadar her sayı 0 için, eğer N-1 ise:
    • Yer tutucu tanımı
      • Sol süslü parantez ({) karakteri
      • I ondalık gösterimi
      • Ardından, karşılık gelen regular_interpolation ya da verbatim_interpolation , interpolation_minimum_widthvarsa, virgül (,) ve ardından constant_expression değerinin ondalık değerin gösterimi.
      • Regular_Interpolation_Format veya Verbatim_Interpolation_Formatkarakterleri, varsa, ilgili regular_interpolation veya verbatim_interpolation
      • Sağ ayraç (}) karakteri
    • Interpolated_Regular_String_Mid veya Interpolated_Verbatim_String_Mid karakterleri, eğer varsa, ilgili interpolasyonun hemen ardından gelir.
  • Son olarak Interpolated_Regular_String_End veya Interpolated_Verbatim_String_End karakterleri.

Sonraki argümanlar, varsa enterpolasyonlardan sırayla ifadesi'lerdir.

Bir interpolated_string_expression birden çok ilişkilendirme içerdiğinde, bu ilişkilendirmelerdeki ifadeler soldan sağa metin düzeninde değerlendirilir.

Örnek:

Bu örnekte aşağıdaki biçim belirtimi özellikleri kullanılır:

  • tamsayıları büyük harflerle onaltılık olarak biçimlendiren X biçim belirtimi,
  • string değerin varsayılan biçimi değerin kendisidir,
  • belirtilen minimum alan genişliğinde sağa dayalı pozitif hizalama değerleri,
  • belirtilen minimum alan genişliği içinde sola yaslayan negatif hizalama değerleri,
  • interpolation_minimum_widthiçin tanımlanan sabitler ve
  • {{ ve }} sırasıyla { ve } olarak biçimlendirilir.

Verilen:

string text = "red";
int number = 14;
const int width = -4;

Sonra:

Ara Eklemeli Dize İfadesi string Anlamına Eşdeğer Değer
$"{text}" string.Format("{0}", text) "red"
$"{{text}}" string.Format("{{text}}) "{text}"
$"{ text , 4 }" string.Format("{0,4}", text) " red"
$"{ text , width }" string.Format("{0,-4}", text) "red "
$"{number:X}" string.Format("{0:X}", number) "E"
$"{text + '?'} {number % 3}" string.Format("{0} {1}", text + '?', number % 3) "red? 2"
$"{text + $"[{number}]"}" string.Format("{0}", text + string.Format("[{0}]", number)) "red[14]"
$"{(number==0?"Zero":"Non-zero")}" string.Format("{0}", (number==0?"Zero":"Non-zero")) "Non-zero"

son örnek

12.8.4 Basit adlar

simple_name, bir tanımlayıcıdan oluşur ve ardından isteğe bağlı olarak bir tür bağımsız değişken listesi gelebilir.

simple_name
    : identifier type_argument_list?
    ;

simple_name, I veya I<A₁, ..., Aₑ> biçiminde olabilir; burada I tek bir tanımlayıcı ve I<A₁, ..., Aₑ> isteğe bağlı bir type_argument_listtir. type_argument_list tanımlanmadığında, e'yi sıfır olarak varsayın. simple_name değerlendirilir ve aşağıdaki gibi sınıflandırılır:

  • e sıfır ise ve simple_name, adlı yerel değişkeni, parametreyi veya sabiti doğrudan içeren bir yerel değişken bildirim alanında (I) görünüyorsa, simple_name bu yerel değişkene, parametreye veya sabite başvurur ve değişken veya değer olarak sınıflandırılır.
  • e sıfırsa ve simple_name, genel bir yöntem bildiriminde ama method_declaration'nın öznitelikleri dışında yer alıyorsa ve bu bildirim Iadlı bir tür parametresi içeriyorsa, o zaman simple_name bu tür parametresine başvurur.
  • Aksi takdirde, dolaysız kapsayan tür bildirimindeki örnek türle başlayarak, her kapsayan sınıf veya yapının bildirimindeki (varsa) örnek türle devam eden T (§15.3.2) örnek türü:
    • e sıfırsa ve T bildirimi Iadlı bir tür parametresi içeriyorsa, simple_name bu tür parametresine başvurur.
    • Aksi takdirde, içindeki I'nin T tür bağımsız değişkenleriyle üye araması (e) eşleşme oluşturursa:
      • T hemen kapsayan sınıfın veya yapı türünün örnek türüyse ve arama bir veya daha fazla yöntemi tanımlarsa, sonuç ilişkili örnek ifadesi thisolan bir yöntem grubudur. Tür bağımsız değişken listesi belirtildiyse, genel bir yöntemi çağırmak için kullanılır (§12.8.10.2).
      • Aksi takdirde, hemen kapsayan sınıfın veya yapı türünün örnek türüyse, arama bir örnek üyesi tanımlarsa ve başvuru bir örnek oluşturucusunun, örnek yönteminin veya örnek erişimcisinin (§12.2.1) bloğunda gerçekleşirse, sonuç, formun üye erişimiyle (§12.8.7) aynıdır. Bu yalnızca e sıfır olduğunda gerçekleşebilir.
      • Aksi takdirde, sonuç form veya T.Iüye erişimiyle (T.I<A₁, ..., Aₑ>) aynıdır.
  • Aksi takdirde, N'nin oluştuğu ad alanından başlayarak, her kapsayıcı ad alanlarıyla (varsa) devam eden ve genel ad alanıyla biten her ad alanı için, bir varlık bulunana kadar aşağıdaki adımlar uygulanır.
    • e sıfırsa ve INiçindeki bir ad alanının adıysa:
      • simple_name oluştuğu konum N için bir ad alanı bildirimiyle kapsanıyorsa ve ad alanı bildirimi ad alanı veya türle ilişkilendiren bir extern_alias_directive veya I içeriyorsa, simple_name belirsizdir ve derleme zamanı hatası oluşur.
      • Aksi takdirde, simple_name, Iiçindeki N adlı ad alanına atıfta bulunur.
    • Aksi takdirde, N erişilebilir bir tür içeriyorsa, ismi I ve e tür parametrelerine sahipse:
      • e sıfır ise ve basit_ad oluştuğu yer, N için bir ad alanı bildirimiyle kapsanmışsa ve bu ad alanı bildirimi, adı ile bir ad alanı veya türle ilişkilendiren bir extern_alias_directive veya I içeriyorsa, o zaman basit_ad belirsizdir ve bir derleme zamanı hatası oluşur.
      • Aksi takdirde, namespace_or_type_name, verilen tür bağımsız değişkenleriyle oluşturulan türe başvurur.
    • Aksi takdirde, simple_name oluştuğu konum Niçin bir ad alanı bildirimi içine alınırsa:
      • e sıfır ise ve ad alanı bildirimi, extern_alias_directive veya using_alias_directive ile içe aktarılan bir ad alanı veya türle ilişkilendirilen I içeriyorsa, simple_name bu ad alanına veya türe başvurur.
      • Aksi takdirde, ad alanı bildiriminin using_namespace_directivetarafından içeri aktarılan ad alanları, ad I ve e tür parametrelerine sahip tam olarak bir tür içeriyorsa, simple_name verilen tür bağımsız değişkenleriyle oluşturulan bu türe atıfta bulunur.
      • Aksi takdirde, ad alanı bildiriminin using_namespace_directive tarafından içeri aktarılan ad alanları, ad I ve e tür parametreleri içeren birden fazla tür içeriyorsa, simple_name belirsiz olur ve derleme zamanı hatası oluşur.

    Not: Bu adımın tamamı, bir namespace_or_type_name (§7.8) işlenmesinde ilgili adıma tam olarak paraleldir. son notu

  • Aksi takdirde, sıfır ve eI tanımlayıcı _ise , simple_namebasit bir atmadır ve bu bir bildirim ifadesi biçimidir (§12.19).
  • Aksi takdirde, simple_name tanımsız olur ve derleme zamanı hatası oluşur.

12.8.5 Parantezli ifadeler

parantezli ifade, bir ifade parantez içinde bulunmasından oluşur.

parenthesized_expression
    : '(' expression ')'
    ;

parantezli_ifade, parantez içindeki ifade değerlendirilerek hesaplanır. ifadesi parantez içinde bir ad alanı veya tür belirtirse, derleme zamanı hatası oluşur. Aksi takdirde, parenthesized_expression sonucu, içerdiği ifadesinindeğerlendirmesinin sonucudur.

12.8.6 Demet ifadeleri

tuple_expression bir dizi temsil eder ve parantez içine alınmış, virgülle ayrılmış, isteğe bağlı olarak adlandırılmış iki veya daha fazla ifadeden oluşur. deconstruction_expression, örtük olarak yazılan bildirim ifadeleri içeren bir demet için kısa bir sözdizimidir.

tuple_expression
    : '(' tuple_element (',' tuple_element)+ ')'
    | deconstruction_expression
    ;
    
tuple_element
    : (identifier ':')? expression
    ;
    
deconstruction_expression
    : 'var' deconstruction_tuple
    ;
    
deconstruction_tuple
    : '(' deconstruction_element (',' deconstruction_element)+ ')'
    ;

deconstruction_element
    : deconstruction_tuple
    | identifier
    ;

tuple_expression bir demet olarak sınıflandırılır.

Bir deconstruction_expressionvar (e1, ..., en), tuple_expression(var e1, ..., var en)'in kısaltmasıdır ve aynı davranışı izler. Bu durum, deconstruction_expressioniçindeki her bir iç içe geçmiş deconstruction_tupleiçin yinelemeli olarak geçerlidir. Bir deconstruction_expression içinde iç içe yerleştirilmiş her tanımlayıcı bir bildirim ifadesi (§12.19) ekler. Sonuç olarak, bir deconstruction_expression yalnızca basit bir atama işleminin sol tarafında yer alabilir.

Örnek: Aşağıdaki kod üç değişken bildirir: a, b ve c. Her biri bir tamsayıdır ve değeri atanımın sağ tarafındaki tuple'dan atanır.

var (a, b, c) = (1, 2, 3); // a is 1, b is 2, and c is 3.
var sum = a + b + c; // sum is 6.

Atamanın tekil öğelerinin herhangi biri bir dekonstrüksiyon ifadesi olabilir. Örneğin, aşağıdaki yapısızlaştırma ifadesi a ile f arasında altı değişken atar.

var (a, b, (c, d, (e, f))) = (1, 2, (3, 4, (5, 6)));

Bu örnekte, iç içe geçmiş tuple'ların yapısının atamanın her iki tarafında da eşleşmesi gerektiğine dikkat edin.

Sol taraftaki değişkenler örtük olarak yazıldıysa, karşılık gelen ifadenin türü olmalıdır:

(int a, string? b) = (42, null); //OK
var (c, d) = (42, null); // Invalid as type of d cannot be inferred
(int e, var f) = (42, null); // Invalid as type of f cannot be inferred

son örnek

Bir tuple ifadesinin ancak ve ancak her bir öğe ifadesinin Ei türü Tiise türü olur. Tür, tuple ifadesiyle aynı arilikte bir tuple türü olmalıdır; burada her öğe aşağıdakiler tarafından verilir:

  • İlgili konumdaki tanımlama grubu öğesinin adı Niise, tanımlama grubu türü öğesi Ti Niolacaktır.
  • Aksi takdirde, , veya biçimindeyse, aşağıdakilerden biri olmadığı sürece, demet türü öğesi , olacaktır:
    • Tanımlama grubu ifadesinin başka bir öğesi Niadlıdır veya
    • Adı olmayan bir başka tanımlama grubu öğesi, formu Ni, E.Ni veya E?.Niolan bir tanımlama grubu öğesi ifadesine sahiptir veya
    • Ni ItemX biçimindedir, burada X bir 0 ile başlatılmamış ondalık basamak dizisini temsil eder ve bir tanımlama grubu öğesinin konumunu gösterebilir, ancak X öğenin konumunu temsil etmez.
  • Aksi takdirde, küme tipi öğesi Tiolmalıdır.

Tuple ifadesi, eleman ifadelerinin her biri soldan sağa doğru sırayla değerlendirilerek belirlenir.

Tanımlama grubu değeri, bir tanımlama grubu ifadesinden bir tanımlama grubu türüne (§10.2.13) dönüştürülerek, değer olarak yeniden sınıflandırılarak (§12.2.2)) veya onu bir yıkıcı atamanın (§12.23.2) hedefi haline getirilerek elde edilebilir.

Örnek:

(int i, string) t1 = (i: 1, "One");
(long l, string) t2 = (l: 2, null);
var t3 = (i: 3, "Three");          // (int i, string)
var t4 = (i: 4, null);             // Error: no type

Bu örnekte, tüm dörtlü ifadeler geçerlidir. İlk ikisi, t1 ve t2, demet ifadesinin türünü kullanmaz, bunun yerine örtük bir demet dönüşümü uygular. t2durumunda, örtük demet dönüştürmesi, 2'den long'ye ve null'ten string'e olan örtük dönüştürmelere dayanır. Üçüncü tuple ifadesi (int i, string)türüne sahiptir ve bu nedenle bu türden bir değer olarak yeniden sınıflandırılabilir. Öte yandan, t4bildirimi bir hatadır: İkinci öğesinin tipi olmadığından demet ifadesinin de tipi yoktur.

if ((x, y).Equals((1, 2))) { ... };

Bu örnek, demetlerin bazen birden çok parantez katmanına yol açabileceğini göstermektedir, özellikle de demet ifadesi bir metod çağrısının tek bağımsız değişkeni olduğunda.

son örnek

12.8.7 Üye erişimi

12.8.7.1 Genel

member_access, primary_expression, predefined_typeveya qualified_alias_member, ardından "." belirteci, ardından tanımlayıcıve isteğe bağlı olarak type_argument_listtakip eder.

member_access
    : primary_expression '.' identifier type_argument_list?
    | predefined_type '.' identifier type_argument_list?
    | qualified_alias_member '.' identifier type_argument_list?
    ;

predefined_type
    : 'bool' | 'byte' | 'char' | 'decimal' | 'double' | 'float' | 'int'
    | 'long' | 'object' | 'sbyte' | 'short' | 'string' | 'uint' | 'ulong'
    | 'ushort'
    ;

qualified_alias_member üretimi, §14.8'te tanımlanır.

member_access, ya E.I biçimindedir ya da E.I<A₁, ..., Aₑ>biçiminde, burada E, primary_expression, predefined_type veya qualified_alias_member olabilir,I ise tek bir tanımlayıcıyı belirtir ve <A₁, ..., Aₑ> isteğe bağlı bir type_argument_listiçerir. type_argument_list tanımlanmadığında, e'yi sıfır olarak varsayın.

uygulama_erişimi bir birincil_ifade'ye sahip dynamic türünde olarak dinamik şekilde bağlanır (§12.3.3). Bu durumda, üye erişimi türünde dynamicbir özellik erişimi olarak sınıflandırılır. member_access anlamını belirlemek için aşağıdaki kurallar, primary_expressionderleme zamanı türü yerine çalışma zamanı türü kullanılarak çalışma zamanında uygulanır. Eğer bu çalışma zamanı sınıflandırması bir metot grubuna yol açıyorsa, üye erişimi bir primary_expression içeren bir çağrı_düğümüolacaktır.

member_access aşağıdaki gibi değerlendirilir ve sınıflandırılır:

  • e sıfır ve E bir ad alanıysa ve E adı Iolan iç içe bir ad alanı içeriyorsa, sonuç bu ad alanıdır.
  • Aksi takdirde, E bir ad alanıysa ve E, adı I olan ve K tür parametrelerine sahip erişilebilir bir tür içeriyorsa, sonuç verilen tür bağımsız değişkenleriyle oluşturulan türdür.
  • E tür olarak sınıflandırılırsa, E bir tür parametresi değilse ve I tür parametreleriyle E üye araması (K) eşleşme oluşturursa, E.I değerlendirilir ve aşağıdaki gibi sınıflandırılır:

    Not: Böyle bir üye aramasının sonucu bir yöntem grubuysa ve K sıfır olduğunda, yöntem grubu tür parametrelerine sahip yöntemler içerebilir. Bu, tür bağımsız değişken çıkarımında bu tür yöntemlerin dikkate alınmasını sağlar. son notu

    • I bir tür tanımlarsa, sonuç, verilen tür bağımsız değişkenleriyle oluşturulan türdür.
    • I bir veya daha fazla yöntemi tanımlarsa, sonuç ilişkili örnek ifadesi olmayan bir yöntem grubudur.
    • I statik bir özellik tanımlarsa, sonuç ilişkili örnek ifadesi olmayan bir özellik erişimidir.
    • I statik bir alan tanımlarsa:
      • Alan salt okunur durumdaysa ve başvuru, alanın bildirildiği sınıfın veya yapının statik oluşturucusunun dışında oluşuyorsa, sonuç bir değerdir; yani Iiçinde E statik alanın değeridir.
      • Aksi takdirde sonuç, Iiçindeki E statik alanı, yani bir değişkendir.
    • I statik bir olay tanımlarsa:
      • Başvuru, olayın bildirildiği sınıf veya yapı içinde gerçekleşirse ve olay event_accessor_declarations (§15.8.1) kullanılmadan bildirildiyse, E.I tam olarak I statik bir alan gibi işlenir.
      • Aksi takdirde, sonuç ilişkili örnek ifadesi olmayan bir olay erişimidir.
    • I bir sabit tanımlarsa, sonuç bir değerdir, yani bu sabitin değeridir.
    • I bir numaralandırma üyesi tanımlarsa, sonuç bir değerdir ve bu da o numaralandırma üyesinin değeridir.
    • Aksi takdirde, E.I geçersiz bir üye başvurusudur ve derleme zamanı hatası oluşur.
  • E bir özellik erişimi, indeksleyici erişimi, değişken veya değerse, türü Tve tür bağımsız değişkenleriyle I içinde T üye araması (K) bir eşleşme sağlıyorsa, E.I aşağıdaki gibi değerlendirilir ve sınıflandırılır:
    • İlk olarak, E bir özellik veya dizin oluşturucu erişimiyse, özellik veya dizin oluşturucu erişiminin değeri elde edilir (§12.2.2) ve E bir değer olarak yeniden sınıflandırılır.
    • I bir veya daha fazla yöntem tanımlarsa, sonuç Eilişkili örnek ifadesi olan bir yöntem grubudur.
    • I bir örnek özelliği tanımlarsa sonuç, E ilişkili örnek ifadesi ve özelliğin türü olan ilişkili bir tür ile özellik erişimidir. T bir sınıf türüyse, Tile başlayıp temel sınıflarda arama yaparken bulunan özelliğin ilk bildiriminden veya geçersiz kılmasından ilişkili tür belirlenir.
    • T bir class_type ise ve I bu class_typebir örnek alanını tanımlar:
      • E değeri nullise bir System.NullReferenceException atılır.
      • Aksi takdirde, alan salt okunursa ve başvuru, alanın bildirildiği sınıfın örnek oluşturucusunun dışında gerçekleşirse, sonuç bir değerdir; yani Itarafından başvurulan nesnede alanın değeri E.
      • Aksi takdirde sonuç, Itarafından referans verilen nesnedeki E alanı olan bir değişkendir.
    • T bir struct_type ise ve I bu struct_typebir örnek alanını tanımlar:
      • E bir değerse ya da alan salt okunursa ve başvuru, alanın bildirildiği yapının örnek oluşturucusunun dışında oluşuyorsa, sonuç, Itarafından sağlanan yapı örneğinde E alanının değeri olan bir değerdir.
      • Aksi takdirde sonuç, Itarafından verilen yapı örneğinde alan E bir değişkendir.
    • I bir örnek olayı tanımlarsa:
      • Başvuru, olayın bildirildiği sınıf veya yapı içinde gerçekleşirse ve olay event_accessor_declarations (§15.8.1) olmadan bildirilmişse ve başvuru a += veya -= işlecinin sol tarafı olarak gerçekleşmiyorsa, E.I tam olarak I bir örnek alanıymış gibi işlenir.
      • Aksi takdirde, sonuç Eile ilişkili bir örnek ifadesine sahip bir olay erişimidir.
  • Aksi takdirde, E.I bir uzantı yöntemi çağrısı olarak işlenmeye çalışılır (§12.8.10.3). Eğer bu başarısız olursa, E.I geçersiz bir üye referansıdır ve yönlendirme zamanında bir hata oluşur.

12.8.7.2 Özdeş basit adlar ve tür adları

E.Iformun üye erişiminde, E tek bir tanımlayıcıysa ve E olarak anlamı (§12.8.4) sabit, alan, özellik, yerel değişken veya parametre E anlamı ile aynı türdeyse (§7.8.1), E her iki olası anlamı da izin verilir. E.I üye araması hiçbir zaman belirsiz değildir, çünkü I her iki durumda da E türüne mutlaka üye olacaktır. Başka bir deyişle, kural aksi takdirde derleme zamanı hatası oluşabilecek yerlerde E'ın statik üyelerine ve iç içe geçmiş türlerine erişime izin verir.

Örnek:

struct Color
{
    public static readonly Color White = new Color(...);
    public static readonly Color Black = new Color(...);
    public Color Complement() => new Color(...);
}

class A
{
    public «Color» Color;              // Field Color of type Color

    void F()
    {
        Color = «Color».Black;         // Refers to Color.Black static member
        Color = Color.Complement();  // Invokes Complement() on Color field
    }

    static void G()
    {
        «Color» c = «Color».White;       // Refers to Color.White static member
    }
}

Yalnızca açıklayıcı amaçlarla, A sınıfı içinde, Color türüne başvuran Color tanımlayıcısının bu oluşumları «...»ile sınırlandırılır ve Color alanına başvuranlar sınırlanmaz.

son örnek

12.8.8 Null Koşullu Üye Erişimi

null_conditional_member_access, member_access'ün koşullu bir versiyonudur (§12.8.7) ve eğer sonuç türü voidise bağlama zamanı hatasıdır. Null koşul ifadesinin sonuç türü void olabilir mi, bkz. (§12.8.11).

bir null_conditional_member_access bir primary_expression ve ardından "" ve "?." iki belirteci, ardından isteğe bağlı type_argument_list içeren bir tanımlayıcı ve ardından bir null_forgiving_operator önce gelen sıfır veya daha fazla dependent_accesses'den oluşur.

null_conditional_member_access
    : primary_expression '?' '.' identifier type_argument_list?
      (null_forgiving_operator? dependent_access)*
    ;
    
dependent_access
    : '.' identifier type_argument_list?    // member access
    | '[' argument_list ']'                 // element access
    | '(' argument_list? ')'                // invocation
    ;

null_conditional_projection_initializer
    : primary_expression '?' '.' identifier type_argument_list?
    ;

null_koşul_bağlı_erişimi ifadesi EP?.A biçimindedir. E anlamı aşağıdaki gibi belirlenir:

  • P türü null atanabilir bir değer türüyse:

    T, P.Value.Atürü olsun.

    • T, başvuru tipi veya null olmayan değer tipi olduğu bilinmeyen bir tür parametresiyse, derleme zamanı hatası oluşur.

    • T boş olamaz bir değer türüyse, E türü T?olur ve E anlamı, şu anlamla aynıdır:

      ((object)P == null) ? (T?)null : P.Value.A
      

      Sadece P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.

    • Aksi takdirde E'ın türü T'dir ve E'nin anlamı, şu anlamla aynıdır:

      ((object)P == null) ? (T)null : P.Value.A
      

      Sadece P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.

  • Yoksa:

    T P.Aifadesinin türü olmasına izin verin.

    • T, başvuru tipi veya null olmayan değer tipi olduğu bilinmeyen bir tür parametresiyse, derleme zamanı hatası oluşur.

    • T boş olamaz bir değer türüyse, E türü T?olur ve E anlamı, şu anlamla aynıdır:

      ((object)P == null) ? (T?)null : P.A
      

      Sadece P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.

    • Aksi takdirde E'ın türü T'dir ve E'nin anlamı, şu anlamla aynıdır:

      ((object)P == null) ? (T)null : P.A
      

      Sadece P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.

Not: Şu formdaki bir ifade:

P?.A₀?.A₁

Eğer P, null olarak değerlendirilirse, ne A₀ ne de A₁ değerlendirilir. Aynı durum, ifade bir dizi null_conditional_member_access veya null_conditional_element_access§12.8.13 işlemi olduğunda da geçerlidir.

son notu

null_conditional_projection_initializer, null_conditional_member_access kısıtlamasıdır ve aynı semantiğine sahiptir. Yalnızca anonim nesne oluşturma ifadesinde (§12.8.17.3) projeksiyon başlatıcı olarak gerçekleşir.

12.8.9 Null-bağışlayıcı ifadeler

12.8.9.1 Genel

Null bağışlayan ifadenin değeri, türü, sınıflandırması (§12.2) ve güvenli bağlamı (§16.4.15), primary_expression değeri, türü, sınıflandırması ve güvenli bağlamıdır.

null_forgiving_expression
    : primary_expression null_forgiving_operator
    ;

null_forgiving_operator
    : '!'
    ;

Not: Aynı sözcük belirteciyle () temsil edilmelerine rağmen, null'u hoşgören son ek ve mantıksal değil ön ek işleçleri (!) farklıdır. Yalnızca ikincisi aşırı yüklenebilir (§15.10), null-forgiving işlecinin tanımı sabittir. son notu

Null-forgiving işlecinin aynı ifadeye, araya giren parantezlere rağmen birden fazla kez uygulanması derleme zamanı hatasıdır.

Örnek: Aşağıdakilerin tümü geçersiz:

var p = q!!;            // error: applying null_forgiving_operator more than once
var s = ( ( m(t) ! ) )! // error: null_forgiving_operator applied twice to m(t)

son örnek

Bu alt türün geri kalanı ve aşağıdaki eşdüzey alt öğeler koşullu olarak normatiftir.

Statik null durum analizi (§8.9.5) gerçekleştiren bir derleyici aşağıdaki belirtimlere uygun olmalıdır.

Null-forgiving işleci, derleyicinin statik null durum analizini bilgilendirmek için kullanılan bir derleme zamanı sahte işlemidir. İki kullanım alanı vardır: derleyicinin bir ifadenin belki null olduğu belirlemesini geçersiz kılmak; ve null olasılığı ile ilgili bir uyarı veren derleyiciyi geçersiz kılmak için.

Derleyicinin statik null durum analizinin hiçbir uyarı üretmediği bir ifadeye null-forgiving işlecinin uygulanması hata değildir.

12.8.9.2 "null olabilir" belirlemesini geçersiz kılma

Bazı durumlarda bir derleyicinin statik null durum analizi, ifadenin null durumu null olabilir olduğunu saptayabilir ve diğer bilgiler ifadenin null olamayacağını gösterdiğinde bir tanılama uyarısı verebilir. Böyle bir ifadeye null-forgiving işlecinin uygulanması, derleyicinin statik null durum analizine null durumunundeğil olduğunu bildirir. Bu, hem tanılama uyarısını engeller hem de devam eden tüm analizleri bilgilendirebilir.

Örnek: Aşağıdakileri göz önünde bulundurun:

#nullable enable
public static void M()
{
    Person? p = Find("John");                  // returns Person?
    if (IsValid(p))
    {
       Console.WriteLine($"Found {p!.Name}");  // p can't be null
    }
}

public static bool IsValid(Person? person) =>
    person != null && person.Name != null;

IsValid truedöndürürse, p'nin Name özelliğine erişmek için güvenle başvuru yapılabilir ve !kullanılarak "muhtemelen null olan bir değerin başvurusunu kaldırma" uyarısı bastırılabilir.

son örnek

Örnek: Null-forgiving işleci dikkatli kullanılmalıdır, dikkat edilmesi gereken bir örnek:

#nullable enable
int B(int? x)
{
    int y = (int)x!; // quash warning, throw at runtime if x is null
    return y;
}

Burada null-forgiving operatörü bir değer türüne uygulanır ve xüzerindeki herhangi bir uyarıyı bastırır. Ancak x çalışma zamanında null ise, null, int'e türetilmediği için bir istisna fırlatılır.

son örnek

12.8.9.3 Diğer null çözümleme uyarılarını geçersiz kılma

Yukarıdaki gibi null belirlemelerini geçersiz kılmaya ek olarak, bir ifadenin bir veya daha fazla uyarı gerektirdiğine ilişkin derleyicinin statik null durum çözümleme belirlemesini geçersiz kılmanın istendiği başka durumlar da olabilir. Böyle bir ifadeye null-forgiving operatörü uygulandığında, derleyicinin bu ifade için herhangi bir uyarı vermemesi istenir. Yanıt olarak bir derleyici uyarı vermemeyi seçebilir ve ayrıca daha fazla çözümlemesini değiştirebilir.

Örnek: Aşağıdakileri göz önünde bulundurun:

#nullable enable
public static void Assign(out string? lv, string? rv) { lv = rv; }

public string M(string? t)
{
    string s;
    Assign(out s!, t ?? "«argument was null»");
    return s;
}

Assignyöntemi parametrelerinin türleri (lv & rv) string?'tür, lv ise bir çıkış parametresidir ve basit bir atama gerçekleştirir.

Yöntem M, stüründeki stringdeğişkenini Assign'ün çıkış parametresi olarak geçirir; kullanılan derleyici, s'ün null atanabilir bir değişken olmadığını belirterek bir uyarı verecektir. Assign'nin ikinci bağımsız değişkeninin null olamayacağı göz önüne alındığında, uyarıyı bastırmak için null-forgiving işleci kullanılır.

son örnek

Koşullu normatif metnin sonu.

12.8.10 Çağırma ifadeleri

12.8.10.1 Genel

Bir yöntemi çağırmak için bir invocation_expression kullanılır.

invocation_expression
    : primary_expression '(' argument_list? ')'
    ;

Eğer yalnızca delegate_typevarsa, primary_expression bir null_forgiving_expression olabilir.

Aşağıdakilerden en az biri doğruysa, çağırma ifadesi dinamik olarak bağlıdır (§12.3.3).

  • primary_expression derleme zamanı türüne dynamicsahiptir.
  • İsteğe bağlı argument_list en az bir bağımsız değişkeni dynamicderleme zamanı türüne sahiptir.

Bu durumda , invocation_expression türündeki dynamicbir değer olarak sınıflandırılır. invocation_expression anlamını belirlemek için aşağıdaki kurallar, primary_expression ve dynamicderleme zamanı türüne sahip bağımsız değişkenlerin derleme zamanı türü yerine çalışma zamanı türü kullanılarak çalışma zamanında uygulanır. primary_expressiondynamicderleme zamanı türüne sahip değilse, yöntemi çağırma işlemi §12.6.5'de açıklandığı gibi sınırlı bir derleme zamanı denetiminden geçer.

primary_expression ifadesi, bir invocation_expression için bir yöntem grubu veya bir delegate_typedeğeri olmalıdır. primary_expression bir yöntem grubuysa, invocation_expression bir yöntem çağırmadır (§12.8.10.2). primary_expression bir delegate_typedeğeriyse, invocation_expression bir temsilci çağrısıdır (§12.8.10.4). primary_expression bir yöntem grubu veya delegate_typedeğeri değilse bağlama zamanı hatası oluşur.

İsteğe bağlı argument_list (§12.6.2) yöntemin parametreleri için değerler veya değişken başvuruları sağlar.

invocation_expression değerlendirme sonucunun sınıflandırılması aşağıdaki gibidir:

  • invocation_expression değer döndürmeyen bir yöntem (§15.6.1) veya değer döndürmeyen bir temsilci çağırırsa sonuç olmaz. Hiçbir şey olarak sınıflandırılan bir ifadeye yalnızca statement_expression (§13.7) bağlamında veya bir lambda_expression (§12.21) gövdesi olarak izin verilir. Aksi takdirde bağlama zamanı hatası oluşur.
  • Aksi takdirde, invocation_expression bir başvuru ile dönen yöntem (§15.6.1) veya başvuru ile dönen temsilci çağırırsa, sonuç yöntemin veya temsilcinin dönüş türünün ilişkili türdeki bir değişkendir. Eğer çağrı bir örnek metoduna aitse ve alıcı T sınıf türündeyse, ilişkili tür, T ile başlayarak ve temel sınıflarında arama yaparak bulunan metodun ilk bildirimi veya geçersiz kılması arasından seçilir.
  • Aksi takdirde, invocation_expression, değere göre dönen bir yöntemi (§15.6.1) veya değere göre dönen bir temsilciyi çağırır ve sonuç, yöntemin veya temsilcinin dönüş türüyle ilişkili bir değerdir. Eğer çağrı bir örnek metoduna aitse ve alıcı T sınıf türündeyse, ilişkili tür, T ile başlayarak ve temel sınıflarında arama yaparak bulunan metodun ilk bildirimi veya geçersiz kılması arasından seçilir.

12.8.10.2 Yöntem çağrıları

Bir yöntem çağrısı için, primary_expression, invocation_expression'in bir yöntem grubu olması gerekir. Yöntem grubu, çağrılacak tek yöntemi veya çağrılacak belirli bir yöntemin seçileceği aşırı yüklenmiş yöntem kümesini tanımlar. İkinci durumda, çağrılacak belirli yöntemin belirlenmesi, argument_listtarafından sağlanan bağlam temelinde yapılır.

M(A)formundaki bir yöntem çağrısının bağlanma zamanı işlenmesi, burada M bir yöntem grubudur (büyük olasılıkla bir tür_ön_ek_listesidahil) ve A isteğe bağlı bir argüman_listesi'dır, aşağıdaki adımlardan oluşur:

  • Yöntem çağırma için aday yöntemleri kümesi oluşturulur. Fyöntem grubuyla ilişkili her yöntem M için:
    • F genel değilse, F şu durumlarda bir adaydır:
      • M'nun tür bağımsız değişken listesi yok ve
      • F A (§12.6.4.2) ile ilgili olarak geçerlidir.
    • F genelse ve M tür bağımsız değişken listesi yoksa, F aşağıdaki durumlarda bir adaydır:
      • Tür çıkarımı (§12.6.3) başarılı olur, çağrı için tür bağımsız değişkenlerinin bir listesini çıkarır.
      • Çıkarsanan tür bağımsız değişkenleri karşılık gelen yöntem türü parametreleriyle değiştirildikten sonra, F parametre listesinde oluşturulan tüm türler kısıtlamalarını (§8.4.5) karşılar ve F parametre listesi A (§12.6.4.2) için geçerlidir
    • F genelse ve M tür bağımsız değişken listesi içeriyorsa, F aşağıdaki durumlarda bir adaydır:
      • F, tür bağımsız değişkeni listesinde sağlanan yöntem türü parametreleri sayısıyla aynı sayıda.
      • Tür bağımsız değişkenleri karşılık gelen yöntem türü parametreleriyle değiştirildikten sonra, F parametre listesinde oluşturulan tüm türler kısıtlamalarını (§8.4.5) karşılar ve F parametre listesi A (§12.6.4.2) için geçerlidir.
  • Aday yöntemleri kümesi, yalnızca en çok türetilmiş türlerden yöntemleri içerecek şekilde azaltılır: Kümedeki her yöntem C.F için, yöntem C'nin F türünde bildirildiği durumlarda, temel tür C içinde bildirilen tüm yöntemler kümeden kaldırılır. Ayrıca, Cobjectdışında bir sınıf türüyse, arabirim türünde bildirilen tüm yöntemler kümeden kaldırılır.

    Not: Bu ikinci kural yalnızca yöntem grubu, object dışında etkili bir temel sınıfa ve boş olmayan etkin arabirim kümesine sahip bir tür parametresinde üye aramasının sonucu olduğunda etkili olur. son notu

  • Sonuçta elde edilen aday yöntem kümesi boşsa, aşağıdaki adımlar boyunca daha fazla işlem yapılmaz ve bunun yerine çağrı, uzantı metodu olarak yorumlamaya çalışılır (§12.8.10.3). Bu başarısız olursa, geçerli bir yöntem yoktur ve bağlama zamanı hatası oluşur.
  • Aday yöntem kümesinin en iyi yöntemi, §12.6.4aşırı yükleme çözümleme kuralları kullanılarak tanımlanır. Tek bir en iyi yöntem tanımlanamazsa, yöntem çağrısı belirsizdir ve bağlama zamanı hatası oluşur. Aşırı yükleme çözümlemesi gerçekleştirirken, ilgili yöntem türü parametreleri için tür bağımsız değişkenleri (sağlanan veya çıkarılanların) yerine konulduktan sonra genel bir yöntemin parametreleri dikkate alınır.

Yukarıdaki adımlarda bir yöntem seçildikten ve bağlama zamanında doğrulandıktan sonra, gerçek çalışma zamanı çağrısı §12.6.6'de açıklanan işlev üyesi çağırma kurallarına göre işlenir.

Not: Yukarıda açıklanan çözüm kurallarının sezgisel etkisi şu şekildedir: Bir yöntem çağrısı tarafından çağrılan belirli yöntemi bulmak için, yöntem çağrısı tarafından belirtilen türle başlayın ve en az bir uygulanabilir, erişilebilir, geçersiz kılma olmayan yöntem bildirimi bulunana kadar devralma zincirine geçin. Ardından, bu tür içinde bildirilen uygulanabilir, erişilebilir ve geçersiz kılma olmayan yöntemler kümesi üzerinde tür çıkarımı ve aşırı yükleme çözümlemesi yapın ve bu şekilde seçilen yöntemi çağırarak işlemi gerçekleştirin. Yöntem bulunamadıysa, çağırmayı uzantı yöntemi çağırma olarak işlemeyi deneyin. son notu

12.8.10.3 Uzantı yöntemi çağrıları

Formlardan birinin yöntem çağrısında (§12.6.6.2)

«expr» . «identifier» ( )  
«expr» . «identifier» ( «args» )  
«expr» . «identifier» < «typeargs» > ( )  
«expr» . «identifier» < «typeargs» > ( «args» )

çağrının normal işlenmesi geçerli bir yöntem bulmazsa, yapıyı bir uzantı yöntemi çağırma olarak işleme girişiminde bulunulur. «expr» veya «args»'ın herhangi birinin derleme zamanı türü dynamicise, uzantı yöntemleri uygulanmaz.

Amaç, en iyi type_nameCbulmaktır, böylece karşılık gelen statik yöntem çağrıları gerçekleşebilir:

C . «identifier» ( «expr» )  
C . «identifier» ( «expr» , «args» )  
C . «identifier» < «typeargs» > ( «expr» )  
C . «identifier» < «typeargs» > ( «expr» , «args» )

Uzantı yöntemi Cᵢ.Mₑ, şu koşullarda uygun 'dur:

  • Cᵢ genel olmayan, iç içe olmayan bir sınıftır
  • Mₑ'ün adı tanımlayıcıdır
  • Mₑ, yukarıda gösterildiği gibi bağımsız değişkenlere statik bir yöntem olarak uygulandığında erişilebilir ve uygulanabilir
  • ifadesinden türüne, Mₑilk parametresinin türüne uygun olarak örtük bir kimlik, başvuru veya kutulama dönüştürmesi mevcuttur.

C araması aşağıdaki gibi devam eder:

  • En yakın kapsayıcı ad alanı bildiriminden başlayarak, daha sonra her kapsayıcı ad alanı bildirimi üzerinden devam edilerek, ve sonunda içeren derleme birimine ulaşarak uzantı yöntemleri için bir aday kümesi bulmak amacıyla ardışık girişimlerde bulunulur.
    • Verilen ad alanı veya derleme birimi, doğrudan uygun uzantı yöntemleri Cᵢile genel olmayan tür bildirimleri Mₑ içeriyorsa, bu uzantı yöntemlerinden oluşan küme aday kümesidir.
    • Verilen ad alanı veya derleme birimindeki ad alanı yönergeleri kullanılarak içeri aktarılan ad alanları, Cᵢuygun uzantı yöntemleriyle Mₑ genel olmayan tür bildirimlerini doğrudan içeriyorsa, bu uzantı yöntemlerinin kümesi aday kümesidir.
  • Herhangi bir kapsayan ad alanı bildiriminde veya derleme biriminde bir aday kümesi bulunamazsa, derleme hatası oluşur.
  • Aksi takdirde, §12.6.4'de açıklandığı gibi aday kümesine aşırı yükleme çözümlemesi uygulanır. Tek bir en iyi yöntem bulunamazsa derleme zamanı hatası oluşur.
  • C, içinde en iyi yöntemin bir uzantı yöntemi olarak bildirildiği türdür.

Hedef olarak C kullanıldığında yöntem çağrısı statik yöntem çağrısı olarak işlenir (§12.6.6).

Not: Örnek yöntem çağrılarına kıyasla, ifade bir null referansa değerlendirildiğinde herhangi bir istisna oluşturmaz. Bunun yerine, bu null değeri, normal bir statik yöntem çağrısıyla nasıl olurduysa, uzantı yöntemine geçirilir. Bu tür bir çağrıya nasıl yanıt vereceğine karar vermek uzantı yöntemi uygulamasına bağlı. son notu

Yukarıdaki kurallar, örnek yöntemlerinin uzantı yöntemlerinden öncelikli olduğu, iç ad alanı bildirimlerinde kullanılabilen uzantı yöntemlerinin dış ad alanı bildirimlerinde kullanılabilen uzantı yöntemlerine göre öncelikli olduğu ve doğrudan ad alanında bildirilen uzantı yöntemlerinin, bir using namespace yönergesiyle aynı ad alanına aktarılan uzantı yöntemlerine göre öncelikli olduğu anlamına gelir.

Örnek:

public static class E
{
    public static void F(this object obj, int i) { }
    public static void F(this object obj, string s) { }
}

class A { }

class B
{
    public void F(int i) { }
}

class C
{
    public void F(object obj) { }
}

class X
{
    static void Test(A a, B b, C c)
    {
        a.F(1);            // E.F(object, int)
        a.F("hello");      // E.F(object, string)
        b.F(1);            // B.F(int)
        b.F("hello");      // E.F(object, string)
        c.F(1);            // C.F(object)
        c.F("hello");      // C.F(object)
    }
}

Örnekte, B'nin yöntemi ilk uzantı yönteminden önceliklidir ve Cyöntemi her iki uzantı yönteminden de önceliklidir.

public static class C
{
    public static void F(this int i) => Console.WriteLine($"C.F({i})");
    public static void G(this int i) => Console.WriteLine($"C.G({i})");
    public static void H(this int i) => Console.WriteLine($"C.H({i})");
}

namespace N1
{
    public static class D
    {
        public static void F(this int i) => Console.WriteLine($"D.F({i})");
        public static void G(this int i) => Console.WriteLine($"D.G({i})");
    }
}

namespace N2
{
    using N1;

    public static class E
    {
        public static void F(this int i) => Console.WriteLine($"E.F({i})");
    }

    class Test
    {
        static void Main(string[] args)
        {
            1.F();
            2.G();
            3.H();
        }
    }
}

Bu örneğin çıktısı şu şekildedir:

E.F(1)
D.G(2)
C.H(3)

D.G, üzerinde C.Gönceliklidir ve E.F hem D.Fhem de C.F 'den önceliklidir.

son örnek

12.8.10.4 Temsilci çağrıları

Temsilci çağrısı için, primary_expression ifadesi invocation_expression ifadesinin delegate_type türünde bir değeri olmalıdır. Ayrıca, delegate_type delegate_typeile aynı parametre listesine sahip bir işlev üyesi olması göz önünde bulundurularak, delegate_type invocation_expression'ın argument_list'a göre geçerli olacaktır (§12.6.4.2).

D(A), D olan bir primary_expression ve isteğe bağlı bir Aiçeren biçimindeki temsilci çağrısının çalışma zamanı işlemesi aşağıdaki adımlardan oluşur:

  • D değerlendirilir. Bu değerlendirme bir istisnaya neden olursa, başka adımlar yürütülmez.
  • Bağımsız değişken listesi A değerlendirilir. Bu değerlendirme bir istisnaya neden olursa, başka adımlar yürütülmez.
  • D değeri geçerli olup olmadığı kontrol edilir. D değeri nullise bir System.NullReferenceException atılır ve başka adım yürütülmez.
  • Aksi takdirde, D bir temsilci örneğine başvurudur. İşlev üyesi çağrıları (§12.6.6) temsilcinin çağrılan listesindeki çağrılabilen varlıkların her birinde gerçekleştirilir. Örnek ve örnek yöntemi içeren çağrılabilir varlıklar için, çağrı sırasında kullanılacak örnek, çağrılabilir varlığın içindeki örnektir.

Parametre içermeyen birden çok çağrı listesinin ayrıntıları için bkz. §21.6 .

12.8.11 Null Koşullu Çağırma İfadesi

null_conditional_invocation_expression söz dizimi olarak ya null_conditional_member_access (§12.8.8) ya da son dependent_access'in bir çağırma ifadesi olduğu null_conditional_element_access (§12.8.13) şeklindedir (§12.8.10).

null_conditional_invocation_expression bir statement_expression (§13.7), anonymous_function_body (§12.21.1) veya method_body (§15.6.1) bağlamında gerçekleşir.

Sentaks açısından eşdeğer null_conditional_member_access veya null_conditional_element_access'ten farklı olarak, bir null_conditional_invocation_expression hiçbir şey olarak sınıflandırılabilir.

null_conditional_invocation_expression
    : null_conditional_member_access null_forgiving_operator? '(' argument_list? ')'
    | null_conditional_element_access null_forgiving_operator? '(' argument_list? ')'
    ;

İsteğe bağlı null_forgiving_operator, yalnızca null_conditional_member_access veya null_conditional_element_access, delegate_type'ye sahip olduğunda eklenebilir.

null_conditional_invocation_expression ifadesi EP?A biçimindedir; burada A, null_conditional_member_access veya null_conditional_element_access eşdeğerinin geri kalanıdır, bu nedenle A. veya [ ile başlar. ve PAbirleştirmesini P işaretleyelimA.

E bir statement_expression olarak ortaya çıktığında, E anlamı, deyiminin anlamı ile aynıdır:

if ((object)P != null) PA

ancak P yalnızca bir kez değerlendirilir.

E bir anonim fonksiyon gövdesi veya metot gövdesi olarak gerçekleştiğinde, E anlamı sınıflandırmasına bağlıdır:

  • E hiçbir şey olarak sınıflandırılmazsa anlamı bloğunun anlamı ile aynıdır:

    { if ((object)P != null) PA; }
    

    ancak P yalnızca bir kez değerlendirilir.

  • Aksi takdirde E anlamı, bloğununanlamı ile aynıdır:

    { return E; }
    

    ve sırasıyla bu bloğunun anlamı, E'nin null_conditional_member_access (§12.8.8) veya null_conditional_element_access (§12.8.13) ile dilbilgisel olarak eşdeğer olup olmadığına bağlıdır.

12.8.12 Öğe erişimi

12.8.12.1 Genel

Element_access, bir primary_expression, ardından bir "[" belirteci, ardından bir argument_list ve son olarak bir "]" belirtici ile oluşur. argument_list, bir veya daha fazla bağımsız değişkenden oluşur ve bunlar virgülle ayrılır.

element_access
    : primary_expression '[' argument_list ']'
    ;

Hem element_accesshem depointer_element_access (§24.6.4) alternatiflerinin geçerli olup olmadığını primary_expression tanındığında, katıştırılmış primary_expression işaretçi türündeyse (§24.3) ikinci seçenek seçilir.

Bir element_access'in primary_expression'ı, array_initializer içermedikçe array_creation_expression veya stackalloc_initializer içermedikçe stackalloc_expression olamaz.

Not: Bu kısıtlama, aşağıdakiler gibi kafa karıştırıcı olabilecek kodlara izin vermemeye yöneliktir:

    var a = new int[3][1];

aksi takdirde şu şekilde yorumlanabilir:

    var a = (new int[3])[1];

Benzer bir kısıtlama null_conditional_element_access için de geçerlidir (§12.8.13). son notu

Aşağıdakilerden en az biri varsa, element_access dinamik olarak bağlıdır (§12.3.3):

  • primary_expression derleme zamanı türüne dynamicsahiptir.
  • argument_list en az bir ifadesi derleme zamanı türüne dynamicsahiptir.

Bu durumda , element_access derleme zamanı türü, primary_expression derleme zamanı türüne bağlıdır: dizi türü varsa, derleme zamanı türü bu dizi türünün öğe türüdür; aksi takdirde derleme zamanı türü olur dynamic ve element_access türündeki dynamicbir değer olarak sınıflandırılır. Element_access anlamını belirlemek için aşağıdaki kurallar, derleme zamanı türüne sahip primary_expression ve argument_list ifadelerinin derleme zamanı türü yerine çalışma zamanı türü kullanılarak çalışma zamanında uygulanır.dynamic primary_expression derleme zamanı türü dynamicyoksa, öğe erişimi §12.6.5'te açıklandığı gibi sınırlı bir derleme zamanı denetiminden geçer.

Örnek:

var index = (dynamic)1; // index has compile-time type dynamic
int[] a = {0, 1, 2};
var a_elem = a[index];  // dynamically bound, a_elem has compile-time type int
string s = "012";
var s_elem = s[index];  // dynamcially bound, s_elem has compile-time type dynamic

son örnek

bir element_access primary_expression:

  • dizi türündeki bir değer, element_access bir dizi erişimidir (§12.8.12.2);
  • türünde bir değer string , element_access bir dize erişimidir (§12.8.12.3);
  • aksi takdirde , primary_expression bir veya daha fazla dizin oluşturucu üyesi olan bir sınıf, yapı veya arabirim türünün değişkeni veya değeri olmalıdır; bu durumda element_access bir dizin oluşturucu erişimidir (§12.8.12.4).

12.8.12.2 Dizi erişimi

Dizi erişimi için argument_list adlandırılmış bağımsız değişkenler veya başvuruya göre bağımsız değişkenler (§15.6.2.3) içermeyecektir.

argument_list ifade sayısı, array_type derecesiyle aynı olacaktır ve her ifade şöyle olacaktır:

  • , , intuintveya veya türünde longulong
  • yalnızca tek dereceli dizi erişimi için, veya türünde Index ; veya Range
  • yukarıdaki türlerden birine veya daha fazlasına örtük olarak dönüştürülebilir olmalıdır.

bir array_type P[A]P dizin ifadelerinin argument_list olan formununA dizi erişiminin çalışma zamanı işlemesi aşağıdaki adımlardan oluşur:

  • P değerlendirilir. Bu değerlendirme bir istisnaya neden olursa, başka adımlar yürütülmez.
  • argument_list her dizin ifadesi için soldan sağa doğru sırayla:
    • Dizin ifadesi değerlendirilir, sonuç değerinin türü T olur;
    • Bu değer daha sonra, yalnızca intuint tek sıralı dizi erişimi için veya long örtük dönüştürmenin (ulong) bulunduğu türlerden IndexRangeilkine dönüştürülür.
    • Bir dizin ifadesinin değerlendirilmesi veya sonraki örtük dönüşüm bir özel duruma yol açarsa, başka dizin ifadeleri değerlendirilmez ve başka bir adım yürütülmez.
  • P değeri geçerli olup olmadığı kontrol edilir. P değeri nullise bir System.NullReferenceException atılır ve başka adım yürütülmez.
  • Yukarıdaki adımlar türdeki Range tek bir dizin değeri ürettiyse:
    • L, tarafından Pbaşvuruda bulunılan dizinin uzunluğu olsun.
    • A L (§18.3) bakımından geçerli olup olmadığını denetler. Aksi takdirde bir System.ArgumentOutOfRangeException oluşturulur ve başka bir adım yürütülür.
    • L ile ilgili olarak başlangıç uzaklığı, S ve A öğelerinin sayısı (GetOffsetAndLength) için açıklandığı gibi belirlenir.
    • Dizi erişiminin sonucu, S dizininden başlayarak P öğelerinin sığ bir kopyasını içeren bir dizidir. N sıfır ise dizide sıfır öğe bulunur.

Not:Hem S hem de N sıfır (24,3 ABD doları) olabilir. Boş bir dizinin dizini genellikle geçersizdir, ancak sıfırdan başlayan boş bir aralıkla dizin oluşturmak geçerli olur ve boş bir dizi döndürür. Tanım ayrıca S'ninL, geçmiş uç dizini (§18.1) olmasını sağlar ve bu durumda N sıfır olur ve boş bir dizi döndürülür. son notu

Not: Dizi erişimi kullanılarak bir dizi öğesi aralığına atanamaz. Bu, dizin oluşturucu erişimlerinden (§12.8.12.4) farklıdır. Bu, bir Range değer tarafından belirtilen dizin aralığına atamayı desteklese de gerekmeyebilir. son notu

  • Yoksa:
    • Dizi erişimini değerlendirmenin sonucu, dizinin öğe türünün değişken başvurusudur (§9,5).
    • argument_list içindeki her ifadenin değeri, Ptarafından başvuruda bulunılan dizi örneğinin her boyutunun gerçek sınırlarına göre denetlenir. Eğer bir veya daha fazla değer aralık dışındaysa, bir System.IndexOutOfRangeException oluşturulur ve başka adım yürütülmez.
    • Dizin ifadeleri tarafından verilen dizi öğesinin değişken başvurusu hesaplanır ve bu, dizi erişiminin sonucu olur.

12.8.12.3 Dize erişimi

Bir dize erişimi için element_access argument_list şu şekilde olacak tek bir adsız değer bağımsız değişkeni (§15.6.2.2) içermelidir:

  • veya veya inttüründe IndexRange
  • yukarıdaki türlerden birine veya daha fazlasına örtük olarak dönüştürülebilir.

türü primary_expression ve P[A]P olan formun stringdize erişiminin A çalışma zamanı işlemesi aşağıdaki adımlardan oluşur:

  • P değerlendirilir. Bu değerlendirme bir istisnaya neden olursa, başka adımlar yürütülmez.
  • Dizin ifadesi değerlendirilir, sonuç değerinin türü T olur;
  • Bu değer daha sonra int örtük dönüştürmenin (Index) var olduğu , veya Rangetürlerinin ilkine dönüştürülür.
  • Bir dizin ifadesinin değerlendirilmesi veya sonraki örtük dönüşüm bir özel duruma yol açarsa, başka dizin ifadeleri değerlendirilmez ve başka bir adım yürütülmez.
  • P değeri geçerli olup olmadığı kontrol edilir. P değeri nullise bir System.NullReferenceException atılır ve başka adım yürütülmez.
  • Yukarıdaki adımlar türünde Range bir dizin değeri üretmişse:
    • Dize erişimini değerlendirmenin sonucu türündeki string bir değerdir.
    • L, tarafından Pbaşvuruda bulunılan dizenin uzunluğu olsun.
    • AL (§18.3) ile ilgili olarak geçerli olup olmadığı denetlenir, aksi takdirde bir System.ArgumentOutOfRangeException oluşturulur ve başka bir adım yürütülmezse.
    • L ile ilgili olarak başlangıç uzaklığı, S ve A öğelerinin sayısı (GetOffsetAndLength) için açıklandığı gibi belirlenir.
    • Dize erişiminin sonucu, S'den başlayarak P karakterleri kopyalanarak oluşturulan bir dizedir; N sıfır ise dize boştur.

Not:Hem S hem de N sıfır (§18.3) olabilir. Boş bir dizenin dizini genellikle geçersizdir, ancak sıfırdan başlayan boş bir aralıkla dizin oluşturma geçerli olur ve boş bir dize döndürür. Tanım ayrıca S'nin geçmiş uç dizini (§18.1) olan L olmasını ve bu durumda N'nin sıfır ve boş bir dize döndürülmesini sağlar. son notu

  • Yoksa:
    • Dize erişimini değerlendirmenin sonucu türündeki char bir değerdir.
    • Dönüştürülen dizin ifadesinin değeri, tarafından Pbaşvuruda bulunılan dize örneğinin gerçek sınırlarına göre denetlendi. Değer aralık dışındaysa, bir System.IndexOutOfRangeException oluşturulur ve başka adım yürütülür.
    • Dönüştürülen dizin ifadesinin dizeyle uzaklığındaki karakterin değeri, dize P erişiminin sonucu olur.

12.8.12.4 Dizin oluşturucu erişimi

Dizin erişimi için, element_accessin primary_expression kısmı bir sınıf, yapı veya arabirim türünün değişkeni veya değeri olmalı ve bu tür, element_accessin argument_listine uygun bir veya daha fazla dizin oluşturucuyu uygulamalıdır. argument_list bağımsız değişken içermeyecektir outref.

Bir sınıf, yapı veya arabirim türü olan P[A]'nin Pprimary_expression ve TA formundaki dizinleyici erişiminin bağlama zamanı işlenmesi aşağıdaki adımlardan oluşur:

  • T tarafından sağlanan dizin oluşturucular seti oluşturuldu. Küme, T'da veya T'in temel bir türünde bildirilen, geçersiz kılma bildirimleri olmayan ve bulunduğu bağlamda erişilebilen (§7.5) tüm indeksleyicilerden oluşur.
  • Küme, geçerli olan ve diğer dizin oluşturucular tarafından gizlenmeyen dizin oluşturuculara indirgenir. Kümedeki her dizin oluşturucu S.I aşağıdaki kurallar uygulanır ve burada S dizin oluşturucu I bildirildiği türdür:
    • I A (§12.6.4.2) ile ilgili olarak geçerli değilse I kümeden kaldırılır.
    • I (A) ile ilgili geçerliyse, temel S türünde bildirilen tüm dizin oluşturucular kümeden kaldırılır.
    • I A (§12.6.4.2) için geçerliyse ve Sobjectdışında bir sınıf türüyse, arabirimde bildirilen tüm dizin oluşturucular kümeden kaldırılır.
  • Sonuçta elde edilen aday dizin oluşturucu kümesi boşsa, geçerli dizin oluşturucu yoktur ve bağlama zamanı hatası oluşur.
  • Aday dizin oluşturucu kümesinin en iyi dizin oluşturucuları, §12.6.4aşırı yükleme çözümleme kuralları kullanılarak tanımlanır. Tek bir en iyi dizin oluşturucu tanımlanamıyorsa dizin oluşturucu erişimi belirsizdir ve bağlama zamanı hatası oluşur.
  • En iyi dizin oluşturucunun erişimcileri denetlendi:
    • Dizin oluşturucu erişimi bir atamanın hedefiyse, dizin oluşturucunun bir kümesi veya başvuru alma erişimcisi olmalıdır, aksi takdirde bağlama zamanı hatası oluşur;
    • Aksi takdirde dizin oluşturucunun alma veya başvuru alma erişimcisi olmalıdır, aksi takdirde bağlama zamanı hatası oluşur.

Dizin oluşturucu erişiminin çalışma zamanı işlemesi aşağıdaki adımlardan oluşur:

  • Hedef primary_expressionP değerlendirilir.
  • argument_listA dizin ifadeleri soldan sağa doğru sırayla değerlendirilir.
  • Bağlama zamanında belirlenen en iyi dizin oluşturucuyu kullanma:
    • Dizin oluşturucu erişimi bir atamanın hedefiyse, yeni bir değer atamak için küme erişimcisi veya başvuru alma erişimcisi çağrılır (§12.23.2).
    • Diğer tüm durumlarda, geçerli değeri (§12.2.2) almak için alma erişimcisi veya başvuru alma erişimcisi çağrılır.

12.8.13 Null Koşullu Öğe Erişimi

null_conditional_element_access bir primary_expression ve ardından "?" ve "[" iki belirteci, ardından bir argument_list ve ardından bir "]" belirteci ile sıfır veya daha fazla dependent_access'ten oluşur ve bunların herhangi birinin öncesinde bir null_forgiving_operator olabilir.

null_conditional_element_access
    : primary_expression '?' '[' argument_list ']'
      (null_forgiving_operator? dependent_access)*
    ;

Null koşullu eleman erişimi (null_conditional_element_access) için

null_conditional_element_access içindeki bir primary_expression, array_initializer içermediği sürece array_creation_expression veya stackalloc_initializer içermediği sürece bir stackalloc_expression olmamalıdır.

Not: Bu kısıtlama, kafa karıştırıcı olabilecek kodlara izin vermemeye yöneliktir. Benzer bir kısıtlama, dışlananların bir örneğinin bulunabileceği element_access (§12.8.12) için de geçerlidir. son notu

null_conditional_element_access, element_access koşullu sürümüdür (§12.8.12) ve sonuç türü voidise bağlama zamanı hatasıdır. Null koşul ifadesinin sonuç türü void olabilir mi, bkz. (§12.8.11).

E ifadesi P?[A]Bbiçimindedir; burada B varsa dependent_accesses'leridir. E anlamı aşağıdaki gibi belirlenir:

  • P türü null atanabilir bir değer türüyse:

    T P.Value[A]Bifadesinin türü olmasına izin verin.

    • T, başvuru tipi veya null olmayan değer tipi olduğu bilinmeyen bir tür parametresiyse, derleme zamanı hatası oluşur.

    • T boş olamaz bir değer türüyse, E türü T?olur ve E anlamı, şu anlamla aynıdır:

      ((object)P == null) ? (T?)null : P.Value[A]B
      

      Sadece P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.

    • Aksi takdirde E'ın türü T'dir ve E'nin anlamı, şu anlamla aynıdır:

      ((object)P == null) ? null : P.Value[A]B
      

      Sadece P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.

  • Yoksa:

    T P[A]Bifadesinin türü olmasına izin verin.

    • T, başvuru tipi veya null olmayan değer tipi olduğu bilinmeyen bir tür parametresiyse, derleme zamanı hatası oluşur.

    • T boş olamaz bir değer türüyse, E türü T?olur ve E anlamı, şu anlamla aynıdır:

      ((object)P == null) ? (T?)null : P[A]B
      

      Sadece P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.

    • Aksi takdirde E'ın türü T'dir ve E'nin anlamı, şu anlamla aynıdır:

      ((object)P == null) ? null : P[A]B
      

      Sadece P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.

Not: Şu formdaki bir ifade:

P?[A₀]?[A₁]

Eğer P, null olarak değerlendirilirse, ne A₀ ne de A₁ değerlendirilir. İfade, bir null_conditional_element_access dizisi veya bir null_conditional_member_accessdizisi olduğunda, aynı durum §12.8.8 işlemleri için geçerlidir.

son notu

12.8.14 Bu erişim

this_accessthisanahtar sözcüğünden oluşur.

this_access
    : 'this'
    ;

this_access yalnızca bir örnek oluşturucu, bir örnek metod, bir örnek erişimci (§12.2.1) veya bir sonlandırıcı içerisindeki blok izin verilir. Aşağıdaki anlamlardan birine sahiptir:

  • this, bir sınıfın örnek oluşturucusunda birincil_ifade kullanıldığında, değer olarak sınıflandırılır. Değerin türü, kullanımın gerçekleştiği sınıfın örnek türüdür (§15.3.2) ve değer, oluşturulmuş nesneye bir başvurudur.
  • this bir sınıfın örnek yöntemi veya örnek erişimcisi içindeki bir primary_expression kullanıldığında, değer olarak sınıflandırılır. Değerin türü, kullanımın gerçekleştiği sınıfın örnek türüdür (§15.3.2), değer ise yöntemin veya erişimcinin çağrıldığı nesneye başvurudur.
  • this bir yapının örnek oluşturucusunda bir primary_expression kullanıldığında, değişken olarak sınıflandırılır. Değişkenin türü, kullanımın gerçekleştiği yapının örnek türüdür (§15.3.2) ve değişken de yapıyı temsil eder.
    • Oluşturucu bildiriminde oluşturucu başlatıcısı yoksa, this değişkeni yapı türünün çıkış parametresiyle tam olarak aynı şekilde davranır. Özellikle bu, değişkenin örnek oluşturucusunun her yürütme yolunda kesinlikle atanacağı anlamına gelir.
    • Aksi takdirde, this değişkeni yapı türünün ref parametresiyle tam olarak aynı şekilde davranır. Bu, özellikle değişkenin başlangıçta atanmış olarak kabul edildiği anlamına gelir.
  • this, bir yapının örnek yöntemi veya örnek erişimcisi içindeki bir primary_expression kullanıldığında, değişken olarak sınıflandırılır. Değişkenin türü, kullanımın gerçekleştiği yapının örnek türüdür (§15.3.2).
    • Yöntem veya erişimci bir yineleyici (§15.15) veya zaman uyumsuz işlev (§15.14) this değilse, değişken yöntemin veya erişimcinin çağrıldığı yapıyı temsil eder.
      • Yapı bir readonly structise, this değişkeni yapı türünün giriş parametresiyle tam olarak aynı şekilde davranır.
      • Aksi takdirde this değişkeni, yapı türünün ref parametresiyle tam olarak aynı şekilde davranır
    • Yöntem veya erişimci bir yineleyici veya zaman uyumsuz işlevse, this değişkeni yöntemin veya erişimcinin çağrıldığı yapının bir kopya temsil eder ve yapı türünün değeri parametresiyle tam olarak aynı şekilde davranır.

Aşağıda listelenenler dışında bir bağlamda this içindeki kullanımı derleme zamanı hatasıdır. Özellikle, statik bir yöntem, statik bir özellik erişimcisi veya bir alan bildirimindeki this içinde 'a başvurmak mümkün değildir.

12.8.15 Temel erişim

base_access, base anahtar sözcüğü ardından bir “.” belirteci ve bir tanımlayıcı ile isteğe bağlı olarak bir tip_argüman_listesi veya köşeli ayraçlar içinde bir argüman_listesi gelir.

base_access
    : 'base' '.' identifier type_argument_list?
    | 'base' '[' argument_list ']'
    ;

base_access, geçerli sınıf veya yapıdaki benzer adlandırılmış üyeler tarafından gizlenen temel sınıf üyelerine erişmek için kullanılır. base_access yalnızca örnek oluşturucusunun gövdesinde, örnek yönteminde, örnek erişimcisinde (§12.2.1) veya sonlandırıcıda izin verilir. Bir sınıf veya yapıda base.I oluştuğunda, I bu sınıfın veya yapının temel sınıfının bir üyesini belirtir. Benzer şekilde, bir sınıfta base[E] oluştuğunda, temel sınıfta geçerli bir dizin oluşturucu bulunacaktır.

Bağlama zamanında, base_access biçimindeki ifadeler base.I ve base[E], tam olarak ((B)this).I ve ((B)this)[E] yazılmış gibi değerlendirilir; burada B, yapının veya sınıfın tanımlandığı sınıfın üst sınıfıdır. Bu nedenle, base.I ve base[E]this.I ve this[E]karşılık gelir, ancak this temel sınıfın bir örneği olarak görüntülenir.

Bir base_access bir sanal işlev üyesine (yöntem, özellik veya indeksleyici) başvurduğunda, çalışma zamanında çağrılacak olan işlev üyesinin saptanması (§12.6.6) değiştirilir. tr-TR: İşe çağrılan işlev üyesi, açısından işlev üyesinin en türetilmiş uygulaması (B) bulunarak belirlenir, ancak bu belirleme, alışılmışın aksine, temel olmayan erişimde olduğu gibi thisçalışma zamanı türüne göre yapılmaz. Bu nedenle, bir sanal işlev üyesinin geçersiz kılınması durumunda, devralınan işlev üyesi uygulamasını çağırmak için bir base_access kullanılabilir. Bir base_access tarafından başvurulan işlev üyesi soyut ise, bağlama zamanı hatası oluşur.

Not: thisaksine base kendi içinde bir ifade değildir. Yalnızca base_access veya constructor_initializer (§15.11.2) bağlamında kullanılan bir anahtar sözcüktür. son notu

12.8.16 Son ek artırma ve azaltma işleçleri

post_increment_expression
    : primary_expression '++'
    ;

post_decrement_expression
    : primary_expression '--'
    ;

Sonek artırma veya azaltma işleminin işleneni değişken, özellik erişimi veya dizin oluşturucu erişimi olarak sınıflandırılan bir ifade olmalıdır. İşlemin sonucu, işlenenle aynı türde bir değerdir.

primary_expression derleme zamanı türüne dynamic sahipse, işleç dinamik olarak bağlıdır (§12.3.3) ve post_increment_expression veya post_decrement_expression derleme zamanı türüne dynamic sahiptir. Aşağıdaki kurallar, primary_expression'in çalışma zamanı türü kullanılarak çalışma zamanında uygulanır.

Sonek artırım veya azaltım işlemi uygulanacak operatör bir özellik veya indeks erişimi ise, özellik veya indeksin hem getir hem de ayar erişimcisi olmalıdır. Bu durum böyle değilse, bir bağlama zamanı hatası oluşur.

Belirli bir işleç uygulamasını seçmek amacıyla tekil operatör aşırı yükleme çözümü (§12.4.4) uygulanır. Aşağıdaki türler için önceden tanımlanmış ++ ve -- işleçleri vardır: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimalve herhangi bir sabit listesi türü. Önceden tanımlanmış ++ işleçleri işlenene 1 ekleyerek üretilen değeri döndürür ve önceden tanımlanmış -- işleçleri de işlenenden 1 çıkararak üretilen değeri döndürür. denetlenen bir bağlamda, bu toplama veya çıkarma işleminin sonucu sonuç türü aralığının dışındaysa ve sonuç türü tam sayı türü veya sabit listesi türüyse, bir System.OverflowException oluşturulur.

Seçilen unary operatörün geri dönüş türünden primary_expressiontürüne örtük bir dönüştürme olacaktır, aksi takdirde derleme zamanında bir hata oluşur.

x++ veya x-- şeklinde bir son ek artırma veya azaltma işleminin çalışma zamanı işlemesi şu adımlardan oluşur:

  • x bir değişken olarak sınıflandırılırsa:
    • x değişkeni üretmek için değerlendirilir.
    • x değeri kaydedilir.
    • x kaydedilen değeri, seçili işlecin bağımsız değişken türüne dönüştürülür ve bu değer bağımsız değişken olarak işleçle çağrılır.
    • işleci tarafından döndürülen değer x türüne dönüştürülür ve xönceki değerlendirmesi tarafından verilen konumda depolanır.
    • x değerinin kaydedilen hali, işlemin sonucu olur.
  • x özellik veya dizin oluşturucu erişimi olarak sınıflandırılmışsa:
    • Örnek ifadesi (x, staticdeğilse) ve x ile ilişkili olan bağımsız değişken listesi (x bir dizin oluşturucu erişimiyse) değerlendirilir ve elde edilen sonuçlar, sonraki get ve set erişimci çağrılarında kullanılır.
    • x'nin alma erişimcisi çağrılır ve döndürülen değer kaydedilir.
    • x kaydedilen değeri, seçili işlecin bağımsız değişken türüne dönüştürülür ve bu değer bağımsız değişken olarak işleçle çağrılır.
    • İşleç tarafından döndürülen değer x türüne dönüştürülür ve x kümesi erişimcisi, değer bağımsız değişkeni olarak bu değerle çağrılır.
    • x değerinin kaydedilen hali, işlemin sonucu olur.

++ ve -- işleçleri ön ek gösterimini de destekler (§12.9.7). veya sonucu, işlemi önce değeri, veya sonucu ise işlemi sonra değeridir. Her iki durumda da, x işlemden sonra aynı değere sahiptir.

Bir operatör ++ veya operatör -- uygulaması, ya sonek ya da ön ek notasyonu kullanılarak çağrılabilir. İki farklı gösterim için ayrı operatör uygulamaları olması mümkün değildir.

12.8.17 Yeni operatör

12.8.17.1 Genel

new işleci, yeni tür örnekleri oluşturmak için kullanılır.

Yeni ifadelerin üç biçimi vardır:

  • Nesne oluşturma ifadeleri, sınıf türlerinin ve değer türlerinin yeni örneklerini oluşturmak için kullanılır.
  • Dizi oluşturma ifadeleri, dizi türlerinin yeni örneklerini oluşturmak için kullanılır.
  • Temsilci oluşturma ifadeleri, temsilci türlerinin örneklerini almak için kullanılır.

new işleci, bir tür örneğinin oluşturulmasını ifade eder, ancak bellek ayırmayı ima etmez. Özellikle, değer türlerinin örnekleri, bulundukları değişkenlerin ötesinde ek bellek gerektirmez ve değer türlerinin örneklerini oluşturmak için new kullanıldığında ayırma gerçekleşmez.

Not: Temsilci oluşturma ifadeleri her zaman yeni örnekler oluşturmaz. İfade yöntem grubu dönüştürme (§10.8) veya anonim işlev dönüştürmesi (§10.7) ile aynı şekilde işlendiğinde, bu durum mevcut bir temsilci örneğinin yeniden kullanılmasına neden olabilir. son notu

12.8.17.2 Nesne oluşturma ifadeleri

12.8.17.2.1 Genel

object_creation_expression, yeni bir class_type veya value_typeörneği oluşturmak için kullanılır.

object_creation_expression
    : 'new' type '(' argument_list? ')' object_or_collection_initializer?
    | 'new' type object_or_collection_initializer
    ;

object_or_collection_initializer
    : object_initializer
    | collection_initializer
    ;

türü olan bir object_creation_expression, class_type, value_typeveya type_parameterolmalıdır. türü, bir tuple_type olamaz veya soyut ya da statik bir class_typeolamaz.

İsteğe bağlı argument_list (§12.6.2) ancak türünün bir class_type veya struct_type olması durumunda izin verilir.

Nesne oluşturma ifadesi, nesne başlatıcı veya koleksiyon başlatıcısı içermesi koşuluyla oluşturucu bağımsız değişken listesini ve kapsayan parantezleri atlayabilir. Oluşturucu bağımsız değişken listesinin atlanması ve parantezlerin alınması boş bir bağımsız değişken listesi belirtmeye eşdeğerdir.

Nesne başlatıcı veya koleksiyon başlatıcı içeren bir nesne oluşturma ifadesinin işlenmesi, önce örnek oluşturucunun işlenmesinden ve ardından nesne başlatıcısı (§12.8.17.2.2) veya koleksiyon başlatıcısı (§12.8.17.2.3) tarafından belirtilen üye veya öğe başlatmalarının işlenmesinden oluşur.

İsteğe bağlı argument_list bağımsız değişkenlerinden herhangi biri derleme zamanı türüne dynamic sahipse, object_creation_expression dinamik olarak bağlıdır (§12.3.3) ve derleme zamanı türü olan dynamic bu bağımsız değişkenlerinin çalışma zamanı türü kullanılarak çalışma zamanında aşağıdaki kurallar uygulanır. Ancak, nesne oluşturma işlemi §12.6.5'de açıklandığı gibi sınırlı bir derleme zamanı denetiminden geçer.

bir new T(A)veya Tise ve isteğe bağlı bir argüman_listesiiçeriyorsa, Abiçimindeki bir nesne_oluşturma_ifadesinin bağlama zamanı işlemesi aşağıdaki adımlardan oluşur:

  • T, bir değer_türü ve A mevcut değilse:
    • object_creation_expression varsayılan bir oluşturucu çağrısıdır. object_creation_expression sonucu, Ttüründe bir değerdir, yani T'de tanımlandığı gibi için varsayılan değerdir.
  • Aksi takdirde, eğer T bir type_parameter ise ve A yoksa:
    • için değer türü kısıtlaması veya oluşturucu kısıtlaması (T) belirtilmemişse, bağlama zamanı hatası oluşur.
    • object_creation_expression sonucu, tür parametresinin bağlı olduğu çalışma zamanı türünün değeridir, yani bu türün varsayılan oluşturucusunu çağırmanın sonucudur. Çalışma zamanı türü bir başvuru türü veya değer türü olabilir.
  • Aksi takdirde, T bir class_type veya struct_typeise:
    • T soyut veya statik bir class_typeise derleme zamanı hatası oluşur.
    • Çağrılacak örnek oluşturucu, §12.6.4aşırı yükleme çözümleme kuralları kullanılarak belirlenir. Aday örnek oluşturucuları topluluğu, T (A) için uygun olan bildirilen tüm erişilebilir örnek oluşturuculardan oluşur. Aday örnek oluşturucu kümesi boşsa veya tek bir en iyi örnek oluşturucu tanımlanamıyorsa, bağlama zamanı hatası oluşur.
    • object_creation_expression sonucu, Ttüründe bir değerdir, yani yukarıdaki adımda belirlenen örnek oluşturucuyu çağırarak üretilen değerdir.
    • Aksi takdirde, object_creation_expression geçersizdir ve bağlama zamanı hatası oluşur.

object_creation_expression dinamik olarak bağlı olsa bile, derleme zamanı türü yine de T'dir.

formundaki yeni şeklindeki bir object_creation_expression, bir class_type veya bir struct_type ve isteğe bağlı bir argument_listolduğunda, aşağıdaki adımlardan oluşan bir çalışma zamanı işlemesinden meydana gelir:

  • T bir class_typeise:
    • Sınıf T'ın yeni bir örneği tahsis edilir. Yeni örneği ayırmak için yeterli bellek yoksa, bir System.OutOfMemoryException oluşturulur ve başka adımlar yürütülmez.
    • Yeni örneğin tüm alanları varsayılan değerlerine (§9.3) başlatılır.
    • Örnek oluşturucu, işlev üyesi çağırma kurallarına (§12.6.6) göre çağrılır. Yeni ayrılan örneğe yapılan bir başvuru otomatik olarak örnek oluşturucusunun içine geçirilir ve örneğe bu oluşturucunun içinden bu şekilde erişilebilir.
  • T bir struct_typeise:
    • T türündeki bir örnek, geçici bir yerel değişken ayırılarak oluşturulur. Bir struct_type örnek oluşturucusunun, oluşturulan örneğin her alanına kesinlikle bir değer ataması gerektiğinden, geçici değişkenin başlatılması gerekmez.
    • Örnek oluşturucu, işlev üyesi çağırma kurallarına (§12.6.6) göre çağrılır. Yeni ayrılan örneğe yapılan bir başvuru otomatik olarak örnek oluşturucusunun içine geçirilir ve örneğe bu oluşturucunun içinden bu şekilde erişilebilir.
12.8.17.2.2 Nesne başlatıcıları

nesne başlatıcı, bir nesnenin sıfır veya daha fazla alanı, özelliği veya dizine alınan öğelerinin değerlerini belirtir.

object_initializer
    : '{' member_initializer_list? '}'
    | '{' member_initializer_list ',' '}'
    ;

member_initializer_list
    : member_initializer (',' member_initializer)*
    ;

member_initializer
    : initializer_target '=' initializer_value
    ;

initializer_target
    : identifier
    | '[' argument_list ']'
    ;

initializer_value
    : expression
    | object_or_collection_initializer
    ;

Nesne başlatıcı, { ve } belirteçleri içine alınmış ve virgülle ayrılmış bir dizi üye başlatıcıdan oluşur. Her bir member_initializer, başlatma için bir hedef belirlemelidir. tanımlayıcı, başlatılan nesnenin erişilebilir bir alanını veya özelliğini adlandırırken, köşeli ayraç içine alınmış bir argument_list, başlatılan nesne üzerinde erişilebilir bir indeksleyici için bağımsız değişkenler belirleyecektir. Bir nesne başlatıcının aynı alan veya özellik için birden fazla üye başlatıcı içermesi hatadır.

Not: Nesne başlatıcının aynı alanı veya özelliği birden çok kez ayarlamasına izin verilmiyor olsa da, dizin oluşturucular için böyle bir kısıtlama yoktur. Bir nesne başlatıcı, dizin oluşturuculara başvuran birden çok başlatıcı hedefi içerebilir ve hatta aynı dizin oluşturucu bağımsız değişkenlerini birden çok kez kullanabilir. son notu

Her initializer_target bir eşittir işareti ve ardından bir ifade, bir nesne başlatıcı veya bir koleksiyon başlatıcı ile takip edilir. Nesne başlatıcısı içindeki ifadelerin, başlatdığı yeni oluşturulan nesneye başvurması mümkün değildir.

bir initializer_targetargument_list (Index) veya (Range) türünde bağımsız değişkenler için örtük destek yoktur.

Eşittir işaretinden sonra bir ifade belirten üye başlatıcısı, hedefe atama (§12.23.2) ile aynı şekilde işlenir.

Eşittir işaretinden sonra nesne başlatıcı belirten bir üye başlatıcı, iç içe nesne başlatıcıdır; yani, katıştırılmış bir nesnenin başlatılmasıdır. Alana veya özelliğe yeni bir değer atamak yerine, iç içe nesne başlatıcıdaki atamalar, alan veya özelliğin üyelerine atama olarak kabul edilir. İç içe nesne başlatıcıları, değer türü olan özelliklere veya değer türüne sahip salt okunur alanlara uygulanamaz.

Eşittir işaretinden sonra bir koleksiyon başlatıcı belirleyen bir üye başlatıcı, gömülü bir koleksiyonun başlatılmasıdır. Hedef alana, özelliğe veya dizin oluşturucuya yeni bir koleksiyon atamak yerine başlatıcıda verilen öğeler hedef tarafından başvuruda bulunılan koleksiyona eklenir. Hedef, §12.8.17.2.3'te belirtilen gereksinimleri karşılayan bir koleksiyon türünde olmalıdır.

Başlatıcı hedefi bir dizin oluşturucuya başvurduğunda, dizin oluşturucuya yönelik bağımsız değişkenler her zaman sadece bir kez hesaplanır. Bu nedenle, bağımsız değişkenler hiç kullanılmasa bile (örneğin, boş bir iç içe başlatıcı nedeniyle), yan etkileri açısından değerlendirilir.

Örnek: Aşağıdaki sınıf iki koordinata sahip bir noktayı temsil eder:

public class Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

Point örneği aşağıdaki gibi oluşturulabilir ve başlatılabilir:

Point a = new Point { X = 0, Y = 1 };

Bu aynı etkiye sahiptir

Point __a = new Point();
__a.X = 0;
__a.Y = 1;
Point a = __a;

burada __a görünmez ve erişilemez geçici değişkendir.

Aşağıdaki sınıf, iki noktadan oluşturulan bir dikdörtgeni ve bir Rectangle örneğinin oluşturulmasını ve başlatılmasını gösterir:

public class Rectangle
{
    public Point P1 { get; set; }
    public Point P2 { get; set; }
}

Rectangle örneği aşağıdaki gibi oluşturulabilir ve başlatılabilir:

Rectangle r = new Rectangle
{
    P1 = new Point { X = 0, Y = 1 },
    P2 = new Point { X = 2, Y = 3 }
};

Bu aynı etkiye sahiptir

Rectangle __r = new Rectangle();
Point __p1 = new Point();
__p1.X = 0;
__p1.Y = 1;
__r.P1 = __p1;
Point __p2 = new Point();
__p2.X = 2;
__p2.Y = 3;
__r.P2 = __p2;
Rectangle r = __r;

burada __r, __p1 ve __p2 görünmez ve erişilemez geçici değişkenlerdir.

Rectangleoluşturucu iki katıştırılmış Point örneğini tahsis ederse, bunlar yeni örnekler atamak yerine katıştırılmış Point örneklerini başlatmak için kullanılabilir:

public class Rectangle
{
    public Point P1 { get; } = new Point();
    public Point P2 { get; } = new Point();
}

Aşağıdaki yapı, yeni örnekler atamak yerine eklenmiş Point örneklerini başlatmak için kullanılabilir:

Rectangle r = new Rectangle
{
    P1 = { X = 0, Y = 1 },
    P2 = { X = 2, Y = 3 }
};

Bu aynı etkiye sahiptir

Rectangle __r = new Rectangle();
__r.P1.X = 0;
__r.P1.Y = 1;
__r.P2.X = 2;
__r.P2.Y = 3;
Rectangle r = __r;

son örnek

12.8.17.2.3 Koleksiyon başlatıcıları

Koleksiyon başlatıcısı bir koleksiyonun öğelerini belirtir.

collection_initializer
    : '{' element_initializer_list '}'
    | '{' element_initializer_list ',' '}'
    ;

element_initializer_list
    : element_initializer (',' element_initializer)*
    ;

element_initializer
    : non_assignment_expression
    | '{' expression_list '}'
    ;

expression_list
    : expression (',' expression)*
    ;

Koleksiyon başlatıcısı, { ve } belirteçleri içine alınmış ve virgülle ayrılmış bir öğe başlatıcı dizisini oluşturur. Her öğe başlatıcısı, başlatılmakta olan koleksiyon nesnesine eklenecek bir öğeyi belirtir ve { ve } belirteçleri ile içine alınmış ve virgülle ayrılmış ifadelerin bir listesinden oluşur. Tek ifadeli bir öğe başlatıcı, küme ayraçları olmadan yazılabilir; fakat üye başlatıcılarla belirsizliği önlemek için atama ifadesi olarak kullanılmasına izin verilmez. non_assignment_expression üretimi §12.24'te tanımlanmıştır.

Örnek: Aşağıda, koleksiyon başlatıcısı içeren bir nesne oluşturma ifadesi örneği verilmiştir:

List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

son örnek

Koleksiyon başlatıcısının uygulandığı koleksiyon nesnesi, System.Collections.IEnumerable uygulayan bir türde olmalıdır veya derleme zamanı hatası oluşur. Belirtilen her öğe için soldan sağa doğru sırasıyla, Addadlı bir üyeyi bulmak için normal üye araması uygulanır. Üye aramasının sonucu bir yöntem grubu değilse, derleme zamanı hatası oluşur. Aksi takdirde, aşırı yük çözümlemesi, öğe başlatıcısının ifade listesinin bağımsız değişken listesi olarak kullanılmasıyla uygulanır ve koleksiyon başlatıcısı oluşan yöntemi çağırır. Bu nedenle, koleksiyon nesnesi her öğe başlatıcı için Add adlı geçerli bir örnek veya uzantı yöntemi içermelidir.

Örnek: Aşağıda, bir kişinin adını ve telefon numarası listesini temsil eden bir sınıfın ve List<Contact>'nin oluşturma ve başlatma gösterimi sağlanmaktadır:

public class Contact
{
    public string Name { get; set; }
    public List<string> PhoneNumbers { get; } = new List<string>();
}

class A
{
    static void M()
    {
        var contacts = new List<Contact>
        {
            new Contact
            {
                Name = "Chris Smith",
                PhoneNumbers = { "206-555-0101", "425-882-8080" }
            },
            new Contact
            {
                Name = "Bob Harris",
                PhoneNumbers = { "650-555-0199" }
            }
        };
    }
}

ile aynı etkiye sahip olan

var __clist = new List<Contact>();
Contact __c1 = new Contact();
__c1.Name = "Chris Smith";
__c1.PhoneNumbers.Add("206-555-0101");
__c1.PhoneNumbers.Add("425-882-8080");
__clist.Add(__c1);
Contact __c2 = new Contact();
__c2.Name = "Bob Harris";
__c2.PhoneNumbers.Add("650-555-0199");
__clist.Add(__c2);
var contacts = __clist;

burada __clist, __c1 ve __c2 görünmez ve erişilemez geçici değişkenlerdir.

son örnek

12.8.17.3 Anonim nesne oluşturma ifadeleri

Anonim türde bir nesne oluşturmak için bir anonymous_object_creation_expression kullanılır.

anonymous_object_creation_expression
    : 'new' anonymous_object_initializer
    ;

anonymous_object_initializer
    : '{' member_declarator_list? '}'
    | '{' member_declarator_list ',' '}'
    ;

member_declarator_list
    : member_declarator (',' member_declarator)*
    ;

member_declarator
    : simple_name
    | member_access
    | null_conditional_projection_initializer
    | base_access
    | identifier '=' expression
    ;

Anonim nesne başlatıcı, anonim bir tür bildirir ve bu türün bir örneğini döndürür. Anonim tür, object'ı doğrudan devralan adsız bir sınıf türüdür. Anonim türün üyeleri, türün bir örneğini oluşturmak için kullanılan anonim nesne başlatıcıdan çıkarılmış salt okunur özellikler dizisidir. Özellikle, formun anonim bir nesne başlatıcısı

new { p₁=e₁,p₂=e₂, ... pᵥ=ev}

formun anonim türünü bildirir

class __Anonymous1
{
    private readonly «T1» «f1»;
    private readonly «T2» «f2»;
    ...
    private readonly «Tn» «fn»;

    public __Anonymous1(«T1» «a1», «T2» «a2»,..., «Tn» «an»)
    {
        «f1» = «a1»;
        «f2» = «a2»;
        ...
        «fn» = «an»;
    }

    public «T1» «p1» { get { return «f1»; } }
    public «T2» «p2» { get { return «f2»; } }
    ...
    public «Tn» «pn» { get { return «fn»; } }
    public override bool Equals(object __o) { ... }
    public override int GetHashCode() { ... }
}

burada her «Tx», karşılık gelen «ex» ifadesinin türüdür. İfade bir member_declarator içinde kullanılan bir türü olmalıdır. Bu nedenle, member_declarator içindeki bir ifadenin null ya da anonim bir işlev olması derleme zamanında bir hatadır.

Anonim bir türün ve onun Equals yöntemine ait parametrenin adları, derleyici tarafından otomatik olarak oluşturulur ve program metninde referans alınamaz.

Aynı program içinde, aynı adlarda ve derleme zamanı türlerinde aynı sırada bir özellik dizisi belirten iki anonim nesne başlatıcı, aynı anonim türde örnekler üretir.

Örnek: Örnekte

var p1 = new { Name = "Lawnmower", Price = 495.00 };
var p2 = new { Name = "Shovel", Price = 26.95 };
p1 = p2;

p1 ve p2 aynı anonim türde olduğundan son satırdaki atamaya izin verilir.

son örnek

Anonim türlerdeki Equals ve GetHashcode yöntemleri, object'den devralınan yöntemleri geçersiz kılar ve özelliklerin Equals ve GetHashcode açısından tanımlanır, böylece aynı anonim türün iki örneği yalnızca tüm özellikleri eşitse eşit olur.

Üye bildirimcisi, basit bir ad (§12.8.4), üye erişimi (§12.8.7), null şartlı projeksiyon başlatıcı §12.8.8 veya temel erişim (§12.8.15) olarak kısaltılabilir. Bu, projeksiyon başlatıcı olarak adlandırılır ve aynı ada sahip bir özelliğin bildirimi ve ataması için kısaltmadır. Özellikle, formların üye bildirimcileri

«identifier», «expr» . «identifier» ve «expr» ? . «identifier»

sırasıyla aşağıdakilere tam olarak eşdeğerdir:

«identifier» = «identifier», «identifier» = «expr» . «identifier» ve «identifier» = «expr» ? . «identifier»

Bu nedenle, bir projeksiyon başlatıcıda tanımlayıcı hem değeri hem de değerin atandığı alanı veya özelliği seçer. Sezgisel olarak, projeksiyon başlatıcısı yalnızca bir değeri değil, aynı zamanda değerin adını da projelendirebilir.

12.8.17.4 Dizi oluşturma ifadeleri

Yeni bir array_typeörneği oluşturmak için array_creation_expression kullanılır.

array_creation_expression
    : 'new' non_array_type '[' expression_list ']' rank_specifier*
      array_initializer?
    | 'new' array_type array_initializer
    | 'new' rank_specifier array_initializer
    ;

İlk formun dizi oluşturma ifadesi, ifade listesinden tek tek ifadelerin her birinin silinmesiyle sonuçlanabilecek türde bir dizi örneği ayırır.

Örnek: new int[10,20] dizi oluşturma ifadesi int[,]türünde bir dizi örneği oluşturur ve yeni int[10][,] dizi oluşturma ifadesi int[][,]türünde bir dizi örneği oluşturur. son örnek

İfade listesindeki her ifade int, uint, longveya ulongtüründe ya da bu türlerden birine veya birden fazlasına örtük olarak dönüştürülebilir olmalıdır. Her ifadenin değeri, yeni ayrılan dizi örneğindeki ilgili boyutun uzunluğunu belirler. Dizi boyutunun uzunluğu zorunlu olmadığından, ifade listesinde negatif değere sahip sabit bir ifadenin olması derleme zamanı hatasıdır.

Güvenli olmayan bir bağlam (§24.2) dışında dizilerin düzeni belirtilmez.

İlk formun dizi oluşturma ifadesi bir dizi başlatıcı içeriyorsa, ifade listesindeki her ifade bir sabit olmalı ve ifade listesi tarafından belirtilen derece ve boyut uzunlukları dizi başlatıcısınınkilerle eşleşmelidir.

İkinci veya üçüncü formun dizi oluşturma ifadesinde, belirtilen dizi türünün veya derece belirticisinin sırası dizi başlatıcınınkiyle eşleşmelidir. Tek boyut uzunlukları, dizi başlatıcısının karşılık gelen iç içe yerleştirme düzeylerinin her birindeki öğe sayısından çıkarılır. Bu nedenle, aşağıdaki bildirimdeki başlatıcı ifade

var a = new int[,] {{0, 1}, {2, 3}, {4, 5}};

tam olarak karşılık gelir

var a = new int[3, 2] {{0, 1}, {2, 3}, {4, 5}};

Üçüncü formun dizi oluşturma ifadesi,örtük olarak yazılan dizi oluşturma ifadesi olarak adlandırılır. İkinci forma benzer, ancak dizinin öğe türü açıkça verilmemiş, ancak dizi başlatıcıdaki ifade kümesinin en iyi ortak türü (§12.6.3.16) olarak belirlenmiştir. rank_specifier en az bir virgül bulunduran çok boyutlu bir dizi için, bu küme, iç içe geçmiş array_initializer'lerde bulunan tüm ifadeleriiçerir.

Dizi başlatıcıları §17.7içinde daha ayrıntılı olarak açıklanmıştır.

Dizi oluşturma ifadesini değerlendirmenin sonucu, yeni ayrılan dizi örneğine başvuru olarak bir değer olarak sınıflandırılır. Dizi oluşturma ifadesinin çalışma zamanı işlemesi aşağıdaki adımlardan oluşur:

  • expression_list boyut uzunluğu ifadeleri soldan sağa doğru sırayla değerlendirilir. Her ifadenin değerlendirilmesinin ardından, aşağıdaki türlerden birine örtük dönüştürme (§10.2) gerçekleştirilir: int, uint, long, ulong. Bu listede örtük dönüştürmenin bulunduğu ilk tür seçilir. Bir ifadenin veya sonraki örtük dönüştürmenin değerlendirilmesi bir istisnaya neden olursa, başka bir ifade değerlendirilmez ve başka bir adım yürütülmez.
  • Boyut uzunlukları için hesaplanan değerler aşağıdaki gibi doğrulanır: Değerlerden biri veya daha fazlası sıfırdan küçükse, bir System.OverflowException fırlatılır ve başka hiçbir adım yürütülmez.
  • Belirtilen boyut uzunluklarına sahip bir dizi nesnesi ayrılır. Yeni örneği ayırmak için yeterli bellek yoksa, bir System.OutOfMemoryException oluşturulur ve başka adımlar yürütülmez.
  • Yeni dizi örneğinin tüm öğeleri varsayılan değerlerine (§9.3) başlatılır.
  • Dizi oluşturma ifadesi bir dizi başlatıcı içeriyorsa, dizi başlatıcıdaki her ifade değerlendirilir ve karşılık gelen dizi öğesine atanır. Değerlendirmeler ve atamalar, ifadelerin dizi başlatıcıda yazıldığı sırayla gerçekleştirilir; diğer bir deyişle, öğeler dizin sırası artırılarak başlatılır ve en sağdaki boyut önce artar. Belirli bir ifadenin değerlendirilmesi veya karşılık gelen dizi öğesine yapılan sonraki atama bir özel duruma neden olursa, başka öğe başlatılmaz (ve kalan öğeler varsayılan değerlerine sahip olur).

Dizi oluşturma ifadesi, dizi türünün öğeleriyle bir dizinin örneğini oluşturmaya izin verir, ancak böyle bir dizinin öğeleri el ile başlatılmalıdır.

Örnek: İfade

int[][] a = new int[100][];

int[]türünde 100 öğe içeren tek boyutlu bir dizi oluşturur. Her öğenin başlangıç değeri null. Aynı dizi oluşturma ifadesinin alt dizileri de örneklemesi mümkün değildir ve bu ifade

int[][] a = new int[100][5]; // Error

Bu, derleme zamanı hatasıyla sonuçlanır. Bunun yerine alt diziler manuel olarak örneklenebilir.

int[][] a = new int[100][];
for (int i = 0; i < 100; i++)
{
    a[i] = new int[5];
}

son örnek

Not: Dizi dizisinin "dikdörtgen" bir şekli olduğunda, yani alt dizilerin tümü aynı uzunlukta olduğunda, çok boyutlu bir dizi kullanmak daha verimli olur. Yukarıdaki örnekte dizi dizisinin örneklemesi 101 nesne (bir dış dizi ve 100 alt dizi) oluşturur. Buna karşılık,

int[,] a = new int[100, 5];

yalnızca tek bir nesne, iki boyutlu bir dizi oluşturur ve ayırmayı tek bir deyimde gerçekleştirir.

son notu

Örnek: Örtük olarak yazılan dizi oluşturma ifadelerine örnekler aşağıda verilmiştir:

var a = new[] { 1, 10, 100, 1000 };                     // int[]
var b = new[] { 1, 1.5, 2, 2.5 };                       // double[]
var c = new[,] { { "hello", null }, { "world", "!" } }; // string[,]
var d = new[] { 1, "one", 2, "two" };                   // Error

Ne int ne de string örtük olarak diğerine dönüştürülebildiğinden ve bu nedenle en iyi ortak tür olmadığından, son ifade derleme zamanı hatasına neden olur. Bu durumda açıkça yazılan bir dizi oluşturma ifadesi kullanılmalıdır, örneğin object[]türünü belirtme. Alternatif olarak, öğelerden biri ortak bir temel türe atanabilir ve bu da çıkarılan öğe türü olur.

son örnek

Örtük olarak yazılan dizi oluşturma ifadeleri anonim olarak yazılan veri yapıları oluşturmak için anonim nesne başlatıcılarla (§12.8.17.3) birleştirilebilir.

Örnek:

var contacts = new[]
{
    new
    {
        Name = "Chris Smith",
        PhoneNumbers = new[] { "206-555-0101", "425-882-8080" }
    },
    new 
    {
        Name = "Bob Harris",
       PhoneNumbers = new[] { "650-555-0199" }
    }
};

son örnek

12.8.17.5 Temsilci oluşturma ifadeleri

Bir delegate_typeörneğini elde etmek için delegate_creation_expression kullanılır.

delegate_creation_expression
    : 'new' delegate_type '(' expression ')'
    ;

Temsilci oluşturma ifadesinin bağımsız değişkeni bir yöntem grubu, anonim işlev veya derleme zamanı türü dynamic ya da temsilci_türüdeğeri olmalıdır. Bağımsız değişken bir metot grubuyse, metodu ve bir örnek metod için temsilci oluşturulacak nesneyi tanımlar. Bağımsız değişken anonim bir fonksiyon olduğunda, temsilci hedefinin parametrelerini ve metod gövdesini doğrudan tanımlar. Bağımsız değişken bir değerse, bu değerin bir kopyasını oluşturacağı temsilci örneğini tanımlar.

İfade derleme zamanı türüne dynamicsahipse, delegate_creation_expression dinamik olarak bağlıdır (§12.8.17.5) ve aşağıdaki kurallar, ifadenin çalışma zamanı türü kullanılarak çalışma zamanında uygulanır. Aksi takdirde, kurallar derleme zamanında uygulanır.

Yeni formundaki D(E) bağlama zamanı işlemesi, burada D bir delegate_type ve E bir ifadeolduğunda, aşağıdaki adımlardan oluşur:

  • E bir yöntem grubuysa, temsilci oluşturma ifadesi, 'den E'a bir yöntem grubu dönüştürme (D) ile aynı şekilde işlenir.

  • E anonim bir işlevse, temsilci oluşturma ifadesi 'dan E'a anonim işlev dönüştürmesi (D) ile aynı şekilde işlenir.

  • Bir değerseE, E ile uyumlu olmalıdır (D) ve sonuç, çağıran Etek girişli çağrı listesiyle yeni oluşturulan temsilciye başvurudur.

delegate_creation_expression’in çalışma zamanı işleme süreci, D(E)’ün bir D ve ’nın bir Eolduğu yeni formundaki, aşağıdaki adımlardan oluşur:

  • E bir yöntem grubuysa, temsilci oluşturma ifadesi 'den E'a bir yöntem grubu dönüştürmesi (D) olarak değerlendirilir.
  • E anonim bir işlevse, temsilci oluşturma işlemi E'den D'a (§10.7) anonim işlev dönüştürmesi olarak değerlendirilir.
  • E bir delegate_typedeğeriyse:
    • E değerlendirilir. Bu değerlendirme bir istisnaya neden olursa, başka adımlar yürütülmez.
    • E değeri nullise bir System.NullReferenceException atılır ve başka adım yürütülmez.
    • Temsilci türü D'ün yeni bir örneği tahsis edilir. Yeni örneği ayırmak için yeterli bellek yoksa, bir System.OutOfMemoryException oluşturulur ve başka adımlar yürütülmez.
    • Yeni temsilci örneği, Eçağıran tek girişli bir çağırma listesiyle başlatılır.

Bir temsilcinin çağrı listesi, temsilci örneği oluşturulurken belirlenir ve temsilcinin tüm ömrü boyunca sabit kalır. Başka bir deyişle, bir temsilci oluşturulduktan sonra onun çağrılabilir hedef varlıklarını değiştirmek mümkün değildir.

Not: Unutmayın, iki temsilci birleştirildiğinde veya bir temsilci başka bir temsilciden çıkarıldığında, yeni bir temsilci oluşur; mevcut hiçbir temsilcinin içeriği değiştirilmez. son notu

Bir özelliğe, dizin oluşturucuya, kullanıcı tanımlı işlecine, örnek oluşturucuya, sonlandırıcıya veya statik oluşturucuya başvuran bir temsilci oluşturmak mümkün değildir.

Örnek: Yukarıda açıklandığı gibi, bir yöntem grubundan bir temsilci oluşturulduğunda, aşırı yüklenmiş yöntemlerden hangisinin seçileceğini temsilcinin parametre listesi ve dönüş türü belirler. Örnekte

delegate double DoubleFunc(double x);

class A
{
    DoubleFunc f = new DoubleFunc(Square);

    static float Square(float x) => x * x;
    static double Square(double x) => x * x;
}

A.f alanı, ikinci Square yöntemine başvuran bir temsilciyle başlatılır çünkü bu yöntem parametre listesiyle tam olarak eşleşir ve DoubleFunctürü döndürür. İkinci Square yöntemi mevcut olmasaydı derleme zamanı hatası oluşurdu.

son örnek

12.8.18 Typeof operatörü

typeof işleci, bir tür için System.Type nesnesini almak için kullanılır.

typeof_expression
    : 'typeof' '(' type ')'
    | 'typeof' '(' unbound_type_name ')'
    | 'typeof' '(' 'void' ')'
    ;

unbound_type_name
    : identifier generic_dimension_specifier?
      ('.' identifier generic_dimension_specifier?)*
    | unbound_qualified_alias_member
      ('.' identifier generic_dimension_specifier?)*
    ;

unbound_qualified_alias_member
    : identifier '::' identifier generic_dimension_specifier?
    ;

generic_dimension_specifier
    : '<' comma* '>'
    ;

comma
    : ','
    ;

İlk typeof_expression biçimi, typeof anahtar sözcüğünden ve ardından parantezli bir türden oluşur. Bu formun bir ifadesinin sonucu, belirtilen tür için System.Type nesnesidir. Belirli bir tür için yalnızca bir System.Type nesnesi vardır. Bu, Ttürü için typeof(T) == typeof(T)'in her zaman doğru olduğu anlamına gelir. Türü dynamicolamaz.

İkinci typeof_expression biçimi, bir typeof anahtar sözcüğü ve ardından parantez içine alınmış bir unbound_type_nameiçerir.

Not: unbound_type_name ve unbound_qualified_alias_member grameri, type_name (§7.8) ve qualified_alias_member (§14.8.1) gramerlerini takip eder, ancak generic_dimension_specifier'ler yerine type_argument_list'ler kullanılır. son notu

typeof_expression işlenenini tanırken, eğer hem unbound_type_name hem de type_name uygulanabilirse, yani içinde ne generic_dimension_specifier ne de type_argument_list yoksa, o zaman type_name seçilmelidir.

Not: ANTLR, typeof_expression alternatiflerinin sıralanması nedeniyle belirtilen seçimi otomatik olarak yapar. son notu

bir unbound_type_name anlamı şu şekilde belirlenir:

  • Belirteçler dizisi, her generic_dimension_specifier'yi aynı sayıda virgül ve anahtar sözcüğü ile her type_argument'ın yerini alan bir object ile değiştirerek type_name'e dönüştürülür.
  • Sonuçta elde edilen type_name , bir yapı türüne (§7.8) çözümlenir.
  • unbound_type_name, çözümlenen türle (§8.4) ilişkili ilişkisiz genel türdür.

Not: Bir uygulamanın belirteç dizisini dönüştürmesi veya aracı tarafından oluşturulan türü oluşturması gerekmez, yalnızca belirlenen ilişkisiz genel türün "sanki" olduğu gibi bu işlem izlenmiştir. son notu

Tür adının nullable referans türü olması bir hatadır.

typeof_expression sonucu, sonuçta elde edilen ilişkisiz genel tür için System.Type nesnesidir.

üçüncü typeof_expression biçimi, bir typeof anahtar sözcüğü ve ardından parantez içine alınmış bir void anahtar sözcüğü ile oluşur. Bu formun bir ifadesinin sonucu, bir türün yokluğunu temsil eden System.Type nesnesidir. typeof(void) tarafından döndürülen tür nesnesi, herhangi bir tür için döndürülen tür nesnesinden farklıdır.

Not: Bu özel System.Type nesnesi, dildeki yöntemlere yansımaya izin veren sınıf kitaplıklarında kullanışlıdır; burada bu yöntemler, void yöntemleri de dahil olmak üzere herhangi bir yöntemin dönüş türünü System.Typeörneğiyle temsil etmek ister. son notu

typeof işleci bir tür parametresinde kullanılabilir. Tür adının null atanabilir referans türü olduğu biliniyorsa bu, derleme zamanında hatadır. Sonuç, tür parametresine bağlı çalışma zamanı türü için System.Type nesnesidir. Çalışma zamanı türü null atanabilir bir başvuru türüyse, sonuç karşılık gelen null atanamayan başvuru türüdür. typeof işleci, bir yapı türü veya ilişkisiz genel bir tür üzerinde de kullanılabilir (§8.4.4). İlişkisiz bir genel türün System.Type nesnesi, örnek türünün System.Type nesnesiyle aynı değildir (§15.3.2). Örnek türü, çalışma zamanında her zaman kapalı yapıda bir türdür; bu nedenle, System.Type nesnesi, kullanılan çalışma zamanı türü bağımsız değişkenlerine bağlıdır. Öte yandan, ilişkisiz genel türün tür bağımsız değişkeni yoktur ve çalışma zamanı türü bağımsız değişkenlerinden bağımsız olarak aynı System.Type nesnesini verir.

Örnek: Örnek

class X<T>
{
    public static void PrintTypes()
    {
        Type[] t =
        {
            typeof(int),
            typeof(System.Int32),
            typeof(string),
            typeof(double[]),
            typeof(void),
            typeof(T),
            typeof(X<T>),
            typeof(X<X<T>>),
            typeof(X<>)
        };
        for (int i = 0; i < t.Length; i++)
        {
            Console.WriteLine(t[i]);
        }
    }
}

class Test
{
    static void Main()
    {
        X<int>.PrintTypes();
    }
}

aşağıdaki çıkışı üretir:

System.Int32
System.Int32
System.String
System.Double[]
System.Void
System.Int32
X`1[System.Int32]
X`1[X`1[System.Int32]]
X`1[T]

int ve System.Int32 aynı türde olduğunu unutmayın. "typeof(X<>) sonucu, tür bağımsız değişkenine bağlı değildir; ancak typeof(X<T>) sonucu ondan etkilenir."

son örnek

12.8.19 Sizeof işleci

sizeof işleci, belirli bir türdeki değişkenin kapladığı 8 bit bayt sayısını döndürür. sizeof için işlenici olarak belirtilen tür, bir unmanaged_type (§8.8) olmalıdır.

sizeof_expression
    : 'sizeof' '(' unmanaged_type ')'
    ;

Önceden tanımlanmış bazı türler için sizeof işleci aşağıdaki tabloda gösterildiği gibi sabit bir int değeri verir:

İfade Sonuç
sizeof(sbyte) 1
sizeof(byte) 1
sizeof(short) 2
sizeof(ushort) 2
sizeof(int) 4
sizeof(uint) 4
sizeof(long) 8
sizeof(ulong) 8
sizeof(char) 2
sizeof(float) 4
sizeof(double) 8
sizeof(bool) 1
sizeof(decimal) 16

Tbir enum türü için, sizeof(T) ifadesinin sonucu, yukarıda belirtildiği gibi temel alınan türün boyutuna eşit sabit bir değerdir. Diğer tüm işlenen türleri sizeof için işleç §24.6.9 içinde belirtilir.

12.8.20 İşaretli ve işaretsiz işleçler

checked ve unchecked işleçleri, tamsayı türü aritmetik işlemler ve dönüştürmeler için taşma denetimi bağlamını denetlemek için kullanılır.

checked_expression
    : 'checked' '(' expression ')'
    ;

unchecked_expression
    : 'unchecked' '(' expression ')'
    ;

checked işleci, içerilen ifadeyi denetlenen bir bağlamda değerlendirir ve unchecked işleci de kapsanan ifadeyi işaretlenmemiş bir bağlamda değerlendirir. checked_expression veya unchecked_expression, içerdikleri ifadenin verilen taşma denetimi bağlamında değerlendirildiği dışında, tam olarak bir parenthesized_expression (§12.8.5) ifadesine karşılık gelir.

Taşma denetimi bağlamı checked ve unchecked deyimleri (§13.12) aracılığıyla da denetlenebilir.

Aşağıdaki işlemler, denetlenmiş ve işaretlenmemiş işleçler ve deyimler tarafından oluşturulan taşma denetimi bağlamından etkilenir:

  • İşlenen bir integral veya sabit listesi türünde olduğunda önceden tanımlanmış ++ ve -- işleçler (§12.8.16 ve §12.9.7).
  • Önceden tanımlanmış bir - birli işleci (§12.9.3), işlenen bir integral türde olduğunda.
  • Her iki işlenen de tam sayı veya sabit listesi türünde olduğunda önceden tanımlanmış +, -*, ve / ikili işleçleri (§12.12).
  • Açık sayısal dönüştürmeler (§10.3.2), bir tamsayı veya sabit listesi türünden başka bir tamsayı veya sabit listesi türüne ya da float veya double türünden bir tamsayı veya sabit listesi türüne yapılır.

Yukarıdaki işlemlerden biri hedef türü temsil etmek için çok büyük bir sonuç ürettiğinde, işlemin gerçekleştirildiği bağlam sonuçta elde edilen davranışı denetler:

  • checked Bir bağlamda, işlem sabit bir ifadeyse (§12.25), derleme zamanı hatası oluşur. Aksi takdirde, işlem çalışma zamanında gerçekleştirildiğinde bir System.OverflowException fırlatılır.
  • unchecked bir bağlamda, hedef türe sığmayan yüksek sıralı bitler atılarak sonuç kesilir.

Hiçbir veya işleç veya deyim tarafından checked kapatılmayan sabit olmayan ifadeler (unchecked) (çalışma zamanında değerlendirilen ifadeler) için, dış faktörler (derleyici anahtarları ve yürütme ortamı yapılandırması gibi) denetlenmiş değerlendirme için çağrılmadığı sürece varsayılan taşma denetimi bağlamı işaretlenmez.

Sabit ifadeler (§12.25) (derleme zamanında tam olarak değerlendirilebilen ifadeler) için varsayılan taşma denetimi bağlamı her zaman denetlenmiştir. Sabit bir ifade açıkça unchecked bağlamına yerleştirilmediği sürece, ifadenin derleme zamanı değerlendirmesi sırasında oluşan taşmalar her zaman derleme zamanı hatası oluşturur.

Anonim işlevin gövdesi, anonim işlevin gerçekleştiği checked veya unchecked bağlamlarından etkilenmez.

Örnek: Aşağıdaki kodda

class Test
{
    static readonly int x = 1000000;
    static readonly int y = 1000000;

    static int F() => checked(x * y);    // Throws OverflowException
    static int G() => unchecked(x * y);  // Returns -727379968
    static int H() => x * y;             // Depends on default
}

ifadelerin hiçbiri derleme zamanında değerlendirilemediğinden derleme zamanı hatası bildirilmemiştir. Çalışma zamanında, F yöntemi bir System.OverflowExceptionfırlatır ve G yöntemi aralık dışı sonucun alt 32 bitlik kısmı olan –727379968 değerini döndürür. H yönteminin davranışı, derleme için varsayılan taşma denetimi bağlamını temel alır, ancak F veya Gile aynıdır.

son örnek

Örnek: Aşağıdaki kodda

class Test
{
    const int x = 1000000;
    const int y = 1000000;

    static int F() => checked(x * y);    // Compile-time error, overflow
    static int G() => unchecked(x * y);  // Returns -727379968
    static int H() => x * y;             // Compile-time error, overflow
}

F ve H sabit ifadeler değerlendirilirken oluşan taşmalar, ifadeler checked bağlamda değerlendirildiğinden derleme zamanı hatalarının bildirilmesine neden olur. Gsabit ifadesi değerlendirilirken de taşma meydana gelir, ancak değerlendirme bir unchecked bağlamında gerçekleştiğinden taşma bildirilmiyor.

son örnek

checked ve unchecked işleçleri yalnızca "(" ve ")" belirteçlerinde metin olarak bulunan işlemler için taşma denetimi bağlamını etkiler. İşleçlerin, içerdiği ifadenin değerlendirilmesi sonucunda çağrılan işlev üyeleri üzerinde hiçbir etkisi yoktur.

Örnek: Aşağıdaki kodda

class Test
{
    static int Multiply(int x, int y) => x * y;

    static int F() => checked(Multiply(1000000, 1000000));
}

F'de checked kullanımı, x * yiçindeki Multiply değerlendirilmesini etkilemez, bu nedenle x * y varsayılan taşma denetimi bağlamında değerlendirilir.

son örnek

unchecked operatörü, imzalı tamsayı türlerinin sabitlerini onaltılık gösterimde yazarken kullanışlıdır.

Örnek:

class Test
{
    public const int AllBits = unchecked((int)0xFFFFFFFF);
    public const int HighBit = unchecked((int)0x80000000);
}

Yukarıdaki onaltılık sabitlerin her ikisi de uinttüründedir. Sabitler int aralığının dışında olduğundan, unchecked işleci olmadan int atamaları derleme zamanı hataları üretir.

son örnek

Not: checked ve unchecked işleçleri ve deyimleri, programcıların bazı sayısal hesaplamaların belirli yönlerini denetlemesine olanak sağlar. Ancak bazı sayısal işleçlerin davranışı, işlenenlerinin veri türlerine bağlıdır. Örneğin, açıkça denetlenmemiş bir yapı içinde bile, iki ondalık değerin çarpılması taşmada her zaman bir özel durumla sonuçlanır. Benzer şekilde, iki kayan değerin çarpılması, açıkça denetlenen bir yapı içinde bile taşma durumunda istisna oluşturmaz. Ayrıca, diğer işleçler varsayılan veya açık denetim modundan hiçbir zaman etkilenmez. son notu

12.8.21 Varsayılan değer ifadeleri

Bir türün varsayılan değerini (§9.3) almak için varsayılan değer ifadesi kullanılır.

default_value_expression
    : explicitly_typed_default
    | default_literal
    ;

explicitly_typed_default
    : 'default' '(' type ')'
    ;

default_literal
    : 'default'
    ;

default_literal varsayılan değeri temsil eder (§9.3). Türü yoktur, ancak varsayılan sabit dönüşüm aracılığıyla herhangi bir türe dönüştürülebilir (§10.2.16).

default_value_expression sonucu, bir explicitly_typed_default içindeki açık türün varsayılan (§9,3) veya bir default_value_expression için dönüştürmenin hedef türüdür.

default_value_expression, tür aşağıdakilerden biriyse sabit bir ifadedir (§12,25):

  • referans türü
  • referans türü olduğu bilinen bir tür parametresi (§8.2);
  • aşağıdaki değer türlerinden biri: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool,; veya
  • herhangi bir numaralandırma türü.

12.8.22 Yığın tahsisi

Yığın ayırma ifadesi, yürütme yığınından bir bellek bloğu ayırır. yürütme yığını, yerel değişkenlerin depolandığı bir bellek alanıdır. Yürütme yığını yönetilen yığının bir parçası değildir. Geçerli işlev döndürdüğünde yerel değişken depolama için kullanılan bellek otomatik olarak kurtarılır.

Yığın ayırma ifadesi için güvenli bağlam kuralları §16.4.15.7'de açıklanmıştır.

stackalloc_expression
    : 'stackalloc' unmanaged_type '[' expression ']'
    | 'stackalloc' unmanaged_type? '[' constant_expression? ']' stackalloc_initializer
    ;

stackalloc_initializer
     : '{' stackalloc_initializer_element_list '}'
     ;

stackalloc_initializer_element_list
     : stackalloc_element_initializer (',' stackalloc_element_initializer)* ','?
     ;
    
stackalloc_element_initializer
    : expression
    ;

unmanaged_type (§8.8), yeni ayrılan konumda depolanacak öğelerin türünü ve ifade bu öğelerin sayısını gösterir. Bunlar birlikte alındığında gerekli ayırma boyutunu belirtir. ifade türü örtük olarak inttürüne dönüştürülebilir olmalıdır.

Yığın ayırmanın boyutu negatif olamayacağından, öğe sayısını negatif bir değere değerlendirilen bir ifade olarak (sabiti) belirtmek derleme zamanı hatasıdır.

Çalışma zamanında, ayrılacak öğe sayısı negatif bir değerse davranış tanımlanmamış olur. Sıfırsa, ayırma yapılmaz ve döndürülen değer uygulama tanımlı olur. Öğeleri ayırmak için yeterli bellek mevcut değilse, bir System.StackOverflowException fırlatılır.

Bir stackalloc_initializer mevcut olduğunda:

  • unmanaged_type atlanırsa, stackalloc_element_initializer kümesi için en iyi ortak türe (§12.6.3.16) yönelik kurallar izlenerek çıkarılır.
  • Eğer constant_expression belirtilmezse, stackalloc_element_initializersayısı olarak varsayılır.
  • Bulunuyorsa, constant_expression sayısı stackalloc_element_initializersayısına eşit olmalıdır.

Her stackalloc_element_initializer için unmanaged_type'ye örtük bir dönüşüm olmalıdır (§10.2). stackalloc_element_initializer, ayrılan bellekteki öğeleri dizin sıfırdan başlayarak artan sırada başlatır. bir stackalloc_initializerolmadığında, yeni ayrılan belleğin içeriği tanımlanmamıştır.

bir stackalloc_expression doğrudan bir local_variable_declaration (§13.6.2) başlatma ifadesi olarak gerçekleşirse ve burada local_variable_type bir işaretçi türü (§24.3) veya çıkarılır (var ), stackalloc_expression sonucu türün T* işaretçisidir (§24.9). Bu durumda stackalloc_expression güvenli olmayan kodda görünmelidir. Aksi takdirde, stackalloc_expression işleminin sonucu Span<T>türünden bir instance olacaktır. Burada T, türünden yönetilmeyen bir tür olan.

  • Span<T> (§C.3), bir başvuru yapısı türüdür (§16.2.3) ve burada stackalloc_expressiontarafından ayrılan bellek bloğunu, türlendirilmiş (T) öğelerden oluşan dizinlenebilir bir koleksiyon olarak sunar.
  • Sonucun Length özelliği ayrılan öğe sayısını döndürür.
  • Sonucun dizin oluşturucusu (§15.9), ayrılan bloğun bir öğesine variable_reference (§9.5) döndürür ve aralık kontrol edilir.

Yığın ayırma başlatıcılara catch veya finally bloklarında (§13.11) izin verilmez.

Not: stackallockullanılarak ayrılan belleği açıkça boşaltmanın bir yolu yoktur. son notu

İşlev üyesinin yürütülmesi sırasında oluşturulan tüm yığın üzerinde ayrılan bellek blokları, işlev üyesi döndüğünde otomatik olarak atılır.

stackalloc işleci dışında, C# atık olmayan toplanan belleği yönetmek için önceden tanımlanmış yapı sağlamaz. Bu tür hizmetler genellikle destekleyici sınıf kitaplıkları tarafından sağlanır veya doğrudan temel işletim sisteminden içeri aktarılır.

Örnek:

// Memory uninitialized
Span<int> span1 = stackalloc int[3];
// Memory initialized
Span<int> span2 = stackalloc int[3] { -10, -15, -30 };
// Type int is inferred
Span<int> span3 = stackalloc[] { 11, 12, 13 };
// Error; result is int*, not allowed in a safe context
var span4 = stackalloc[] { 11, 12, 13 };
// Error; no conversion from Span<int> to Span<long>
Span<long> span5 = stackalloc[] { 11, 12, 13 };
// Converts 11 and 13, and returns Span<long> 
Span<long> span6 = stackalloc[] { 11, 12L, 13 };
// Converts all and returns Span<long>
Span<long> span7 = stackalloc long[] { 11, 12, 13 };
// Implicit conversion of Span<T>
ReadOnlySpan<int> span8 = stackalloc int[] { 10, 22, 30 };
// Implicit conversion of Span<T>
Widget<double> span9 = stackalloc double[] { 1.2, 5.6 };

public class Widget<T>
{
    public static implicit operator Widget<T>(Span<double> sp) { return null; }
}

span8durumunda, stackalloc, örtük bir işleç tarafından Span<int>'e dönüştürülen bir ReadOnlySpan<int>ile sonuçlanır. Benzer şekilde, span9için elde edilen Span<double>, gösterildiği gibi dönüştürme kullanılarak kullanıcı tanımlı türe Widget<double> dönüştürülür. son örnek

12.8.23 Nameof operatörü

nameof_expression, bir program varlığının adını sabit dize olarak almak için kullanılır.

nameof_expression
    : 'nameof' '(' named_entity ')'
    ;
    
named_entity
    : named_entity_target ('.' identifier type_argument_list?)*
    ;
    
named_entity_target
    : simple_name
    | 'this'
    | 'base'
    | predefined_type 
    | qualified_alias_member
    ;

nameof bir anahtar sözcük olmadığından, bir nameof_expression her zaman nameofbasit adın çağrılmasıyla sentaktik olarak belirsizdir. Uyumluluk nedeniyle, isim 'nin isim araması (nameof) başarılı olursa, çağrının geçerliliğine bakılmaksızın ifade, bir çalıştırma ifadesi olarak değerlendirilir. Aksi takdirde nameof_expressionifadesidir.

Basit ad ve üye erişim aramaları, §12.8.4 ve §12.8.7'de açıklanan kurallara uyarak derleme zamanında named_entity üzerinde gerçekleştirilir. Ancak, §12.8.4 ve §12.8.7'te tanımlanan arama, statik bağlamda bir örnek üyesi bulunduğu için hatayla sonuçlanırken, nameof_expression böyle bir hataya yol açmaz.

named_entity bir yöntem grubunu belirttiğinde bir type_argument_listolması derleme zamanı hatasıdır. Bir named_entity_target'ın türünün dynamic olarak belirtilmesi derleme zamanı hatasıdır.

nameof_expression, stringtüründe sabit bir ifadedir ve çalışma zamanında hiçbir etkisi yoktur. Özellikle, named_entity değerlendirilmez ve kesin atama analizi (§9.4.4.22) amacıyla göz ardı edilir. type_argument_listparametresinin isteğe bağlı son kısmından önceki named_entity'nin son tanımlayıcısı aşağıdaki şekilde dönüştürülerek elde edilen değerdir.

  • "@" ön eki kullanılırsa kaldırılır.
  • Her unicode_escape_sequence ilgili Unicode karakterine dönüştürülür.
  • Tüm formatting_characters kaldırılır.

Bunlar, tanımlayıcılar arasındaki eşitliği test ederken §6.4.3 uygulanan dönüştürmelerle aynıdır.

Örnek: Aşağıda, nameof ad alanında bildirilen genel bir tür List<T> varsayılarak çeşitli System.Collections.Generic ifadelerinin sonuçları gösterilmektedir:

using TestAlias = System.String;

class Program
{
    static void Main()
    {
        var point = (x: 3, y: 4);

        string n1 = nameof(System);                      // "System"
        string n2 = nameof(System.Collections.Generic);  // "Generic"
        string n3 = nameof(point);                       // "point"
        string n4 = nameof(point.x);                     // "x"
        string n5 = nameof(Program);                     // "Program"
        string n6 = nameof(System.Int32);                // "Int32"
        string n7 = nameof(TestAlias);                   // "TestAlias"
        string n8 = nameof(List<int>);                   // "List"
        string n9 = nameof(Program.InstanceMethod);      // "InstanceMethod"
        string n10 = nameof(Program.GenericMethod);      // "GenericMethod"
        string n11 = nameof(Program.NestedClass);        // "NestedClass"

        // Invalid
        // string x1 = nameof(List<>);            // Empty type argument list
        // string x2 = nameof(List<T>);           // T is not in scope
        // string x3 = nameof(GenericMethod<>);   // Empty type argument list
        // string x4 = nameof(GenericMethod<T>);  // T is not in scope
        // string x5 = nameof(int);               // Keywords not permitted
        // Type arguments not permitted for method group
        // string x6 = nameof(GenericMethod<Program>);
    }

    void InstanceMethod() { }

    void GenericMethod<T>()
    {
        string n1 = nameof(List<T>); // "List"
        string n2 = nameof(T);       // "T"
    }

    class NestedClass { }
}

Bu örneğin potansiyel olarak şaşırtıcı bölümleri, nameof(System.Collections.Generic)'ın tam ad alanı yerine yalnızca "Generic" olarak ve nameof(TestAlias)'in "String" yerine "TestAlias" olarak çözülmesidir. son örnek

12.8.24 Anonim yöntem ifadeleri

anonymous_method_expression, anonim işlev tanımlamanın iki yoludur. Bunlar §12.21'de daha ayrıntılı olarak açıklanmıştır.

12.9 Tekli operatörler

12.9.1 Genel

+, , -! (yalnızca §12.9.4 mantıksal olumsuzlama), ~, ^++, , --, atama ve await işleçler tekli işleçler olarak adlandırılır.

Not: Derleme süresi ve yalnızca aşırı yüklenemeyen doğası nedeniyle, sonek null-forgiving işleci (§12.8.9), ! yukarıdaki listeye dahil edilmemiştir. son notu

unary_expression
    : primary_expression
    | '+' unary_expression
    | '-' unary_expression
    | logical_negation_operator unary_expression
    | '~' unary_expression
    | '^' unary_expression
    | pre_increment_expression
    | pre_decrement_expression
    | cast_expression
    | await_expression
    | pointer_indirection_expression    // unsafe code support
    | addressof_expression              // unsafe code support
    ;

pointer_indirection_expression (§24.6.2) ve addressof_expression (§24.6.5) yalnızca güvenli olmayan kodda (§24) kullanılabilir.

Eğer unary_expression işleneni dynamicderleme zamanı türüne sahipse, dinamik olarak bağlanır (§12.3.3). Bu durumda:

  • unary_expression derleme zamanı türü:
    • Index ^ uçtan uca dizin işleci için (§12.9.6)
    • dynamic diğer tüm birli işleçler için; ve
  • Aşağıda açıklanan çözünürlük, işlenenin çalışma zamanı türü kullanılarak çalışma zamanında gerçekleşir.

12.9.2 Tekli artı operatörü

Bir işlem +xformunda ise, belirli bir operatör uygulamasını seçmek için üni işlemci aşırı yükleme çözümlemesi (§12.4.4) uygulanır. İşlenen, seçilen işlecin parametre türüne dönüştürülür ve sonucun türü işlecin geri dönüş türüdür. Önceden tanımlanmış birli artı işleçleri şunlardır:

int operator +(int x);
uint operator +(uint x);
long operator +(long x);
ulong operator +(ulong x);
float operator +(float x);
double operator +(double x);
decimal operator +(decimal x);

Bu işleçlerin her biri için sonuç yalnızca işlenenin değeridir.

Yukarıda tanımlanan kaldırılmamış ön tanımlı birli artı işleçlerinin kaldırılmış (§12.4.8) formları da önceden tanımlanmıştır.

12.9.3 Tekil eksi işleci

Bir işlem –xformunda ise, belirli bir operatör uygulamasını seçmek için üni işlemci aşırı yükleme çözümlemesi (§12.4.4) uygulanır. İşlenen, seçilen işlecin parametre türüne dönüştürülür ve sonucun türü işlecin geri dönüş türüdür. Önceden tanımlanmış birli eksi işleçleri şunlardır:

  • Tamsayı negatifine çevirme

    int operator –(int x);
    long operator –(long x);
    

    Sonuç, X sıfırdan çıkarılarak hesaplanır. X değeri işlenen türünün en küçük temsil edilebilir değeriyse (int için−2³¹ veya longiçin −2⁶³ ), X matematiksel olumsuzlaması işlenen türü içinde temsil edilemez. Bu bir checked bağlamında oluşursa, bir System.OverflowException oluşturulur; bir unchecked bağlamında gerçekleşirse, sonuç işlenenin değeridir ve taşma bildirilmeyecektir.

    Olumsuzlama işlecinin işleneni uinttüründeyse, longtürüne dönüştürülür ve sonuç longtüründe olur. Özel durum, int değeri −2147483648 (-2³¹) ifadesinin ondalık tamsayı olarak yazılmasına izin veren kuraldır (§6.4.5.3).

    Olumsuzlama işlecinin işleneni ulongtüründe olduğunda, derleme aşaması hatası oluşur. Bir istisna, long değeri −9223372036854775808 (−2⁶³) ondalık tamsayı değişmez değeri olarak yazılmasına izin veren kuraldır (§6.4.5.3)

  • Kayan nokta olumsuzlaması:

    float operator –(float x);
    double operator –(double x);
    

    Sonuç, işareti ters çevrilmiş X değeridir. x NaNise sonuç da NaN.

  • Ondalık olumsuzlama:

    decimal operator –(decimal x);
    

    Sonuç, X sıfırdan çıkarılarak hesaplanır. Ondalık olumsuzlama, System.Decimaltüründeki birli eksi işlecini kullanmaya eşdeğerdir.

Yukarıda tanımlanan kaldırılmamış, önceden tanımlanmış birli eksi işleçlerinin kaldırılmış (§12.4.8) formları da önceden tanımlanmıştır.

12.9.4 Mantıksal olumsuzlama işleci

Bir işlem !xformunda ise, belirli bir operatör uygulamasını seçmek için üni işlemci aşırı yükleme çözümlemesi (§12.4.4) uygulanır. İşlenen, seçilen işlecin parametre türüne dönüştürülür ve sonucun türü işlecin geri dönüş türüdür. Yalnızca bir önceden tanımlanmış mantıksal olumsuzlama işleci vardır:

bool operator !(bool x);

Bu işleç işlenenin mantıksal olumsuzlamasını hesaplar: İşlenen trueise, sonuç falseolur. İşlenen falseolduğunda, sonuç trueolur.

Yukarıda tanımlanan kaldırılmamış önceden tanımlanmış mantıksal olumsuzlama işlecinin lifted (§12.4.8) formları da önceden tanımlanmıştır.

Not: Ön ek mantıksal olumsuzlama ve sonek null-forgiving işleçleri (§12.8.9), aynı sözcük temelli belirteçle (!) temsil edilirken farklıdır. son notu

12.9.5 Bit düzeyinde tamamlayıcı operatörü

Bir işlem ~xformunda ise, belirli bir operatör uygulamasını seçmek için üni işlemci aşırı yükleme çözümlemesi (§12.4.4) uygulanır. İşlenen, seçilen işlecin parametre türüne dönüştürülür ve sonucun türü işlecin geri dönüş türüdür. Önceden tanımlanmış bit düzeyinde tamamlayıcı işleçleri şunlardır:

int operator ~(int x);
uint operator ~(uint x);
long operator ~(long x);
ulong operator ~(ulong x);

Bu işleçlerin her biri için, işlemin sonucu x'ın bit düzeyinde tümleyenidir.

E her numaralandırma türü örtük olarak aşağıdaki bit düzeyinde tamamlayıcı işlecini sağlar:

E operator ~(E x);

~xdeğerlendirildiğinde, X'in, Etemel türüne sahip bir numaralandırma türü U ifadesi olması durumunda elde edilen sonuç, (E)(~(U)x)değerlendirildiğindeki ile aynıdır. Ancak, E'e dönüştürme işlemi her zaman unchecked bağlamındaymış gibi gerçekleştirilir (§12.8.20).

Yukarıda tanımlanan kaldırılmamış önceden tanımlanmış bit düzeyinde tamamlayıcı işleçlerin kaldırılmış (§12.4.8) formları da önceden tanımlanmıştır.

12.9.6 End işlecinden dizin oluşturma

Birli ^ işleç, satır içi olarak şapka işleci olarak adlandırılan, sonundan dizin işleci olarak adlandırılır. Bu işleç aşırı yüklenemez (§12.4.3) ve önceden tanımlanmış tek bir işleç vardır:

Index operator ^(int x);

Formun ^x bir işleminin sonucu, ifadenin sonucuna eşdeğer bir from-end Index (§18.2) değeridir:

new Index(x, true)

Diğer unary_expressionolduğu gibi işlenen de derleme zamanı türüne dynamic (§12.9.1) sahip olabilir ve dinamik olarak bağlı (§12.3.3) olabilir. Sonucun derleme zamanı türü her zaman Indexolur.

Ayrıca, uçtan uca işlecin kaldırılmış (§12.4.8) biçimi de önceden tanımlanmıştır.

12.9.7 Ön ek artırma ve azaltma işleçleri

pre_increment_expression
    : '++' unary_expression
    ;

pre_decrement_expression
    : '--' unary_expression
    ;

Önek artırma veya azaltma işleminin işleneni, değişken, özellik erişimi veya dizinleyici erişimi olarak sınıflandırılmış bir ifade olmalıdır. İşlemin sonucu, işlenenle aynı türde bir değerdir.

Ön ek artırma veya azaltma işleminin işleneni bir özellik veya dizin erişimi ise, bu özellik veya dizin oluşturucunun hem get hem de set erişimcisi olmalıdır. Bu durum böyle değilse, bir bağlama zamanı hatası oluşur.

Belirli bir işleç uygulamasını seçmek amacıyla tekil operatör aşırı yükleme çözümü (§12.4.4) uygulanır. Aşağıdaki türler için önceden tanımlanmış ++ ve -- işleçleri vardır: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimalve herhangi bir sabit listesi türü. Önceden tanımlanmış ++ işleçleri işlenene 1 ekleyerek üretilen değeri döndürür ve önceden tanımlanmış -- işleçleri de işlenenden 1 çıkararak üretilen değeri döndürür. checked bağlamında, bu toplama veya çıkarma işleminin sonucu, sonuç türü aralığının dışındaysa ve sonuç türü tam sayı türü veya sabit listesi türündeyse, bir System.OverflowException atılır.

Seçilen üniter işlecin dönüş tipinden unary_expressiontipine örtük bir dönüştürme olacaktır, aksi takdirde derleme zamanı hatası oluşur.

Form ++x veya --x ön ek artırma veya azaltma işleminin çalışma zamanı işlemesi aşağıdaki adımlardan oluşur:

  • x bir değişken olarak sınıflandırılırsa:
    • x değişkeni üretmek için değerlendirilir.
    • x değeri seçilen işlecin işlenen türüne dönüştürülür ve işleç bağımsız değişkeni olarak bu değerle çağrılır.
    • işleci tarafından döndürülen değer xtürüne dönüştürülür. Elde edilen değer, x değerlendirmesi tarafından verilen konumda depolanır ve işlemin sonucu olur.
  • x özellik veya dizin oluşturucu erişimi olarak sınıflandırılmışsa:
    • Örnek ifadesi (x, staticdeğilse) ve x ile ilişkili olan bağımsız değişken listesi (x bir dizin oluşturucu erişimiyse) değerlendirilir ve elde edilen sonuçlar, sonraki get ve set erişimci çağrılarında kullanılır.
    • x alma erişimcisi çağrılıyor.
    • Get erişimcisi tarafından döndürülen değer, seçilen işlecin işlenen türüne dönüştürülür ve işleç bağımsız değişkeni olarak bu değerle çağrılır.
    • işleci tarafından döndürülen değer xtürüne dönüştürülür. x kümes erişimci, değer argümanı olarak bu değerle çağrılır.
    • Bu değer aynı zamanda işlemin sonucu olur.

++ ve -- işleçleri, sonek gösterimini de destekler (§12.8.16). x++ veya x-- sonucu, işlemden önceki x değeridir, ++x veya --x sonucu ise işlemden sonraki x değeridir. Her iki durumda da, x işlemden sonra aynı değere sahiptir.

Bir operatör ++ veya operatör -- uygulaması, ya sonek ya da ön ek notasyonu kullanılarak çağrılabilir. İki farklı gösterim için ayrı operatör uygulamaları olması mümkün değildir.

Yukarıda tanımlanan kaldırılmamış ön ek artırma ve azaltma işleçlerinin kaldırılmış (§12.4.8) formları da önceden tanımlanmıştır.

12.9.8 Atama ifadeleri

Bir cast_expression, bir ifadeyi açık bir şekilde belirtilen türe dönüştürmek için kullanılır.

cast_expression
    : '(' type ')' unary_expression
    ;

bir tür ve (T)ETolduğu türünden Eformda bir cast_expression, değerinin Etürüne açık bir şekilde dönüştürülmesini (T) gerçekleştirir. E'den T'a açık dönüştürme yoksa bağlama zamanı hatası oluşur. Aksi takdirde, sonuç açık dönüştürme tarafından üretilen değerdir. E bir değişkeni belirtse bile sonuç her zaman bir değer olarak sınıflandırılır.

cast_expression için dilbilgisi kuralları bazı sözdizimsel belirsizliklere yol açar.

Örnek: (x)–y ifadesi, ya 'in –ytürüne çevrilmesi anlamındaki bir x ya da bir parantezli ifade ile birleştirilmiş bir toplama ifadesi olarak yorumlanabilir (bu da x – ydeğerini hesaplar). son örnek

cast_expression belirsizliği çözmek için şu kural vardır: Parantez içine alınmış bir veya daha fazla belirteç dizisi (§6.4), yalnızca aşağıdakilerden en az biri doğruysa cast_expression başlangıcı olarak kabul edilir:

  • Belirteç dizisi, bir tür için doğru dil bilgisidir, ancak bir ifade için değildir.
  • Belirteç dizisi bir tür için doğru dil bilgisidir ve kapatma parantezinden hemen sonra gelen belirteç '~', belirteç '!', belirteç '(', tanıtıcı (§6.4.3), değişmez değer (§6.4.5) veya ve asdışında herhangi bir anahtar sözcük (is) olabilir.

Yukarıdaki "doğru dil bilgisi" terimi yalnızca belirteç sırasının belirli dil bilgisi üretimine uygun olması anlamına gelir. Özellikle herhangi bir kurucu tanımlayıcının gerçek anlamını dikkate almaz.

Örnek: x ve y tanımlayıcıysa, x.y aslında bir türü ifade etmese bile x.y tür için doğru dil bilgisidir. son örnek

Not: Kesinleştirme kuralına göre, x ve y tanımlayıcıysa, (x)y, (x)(y)ve (x)(-y)cast_expression'dir; ancak, (x)-y bir tür tanımlasa bile, x değildir. Ancak, x önceden tanımlanmış bir türü (intgibi) tanımlayan bir anahtar sözcükse, dört formun tümü de cast_expressions olur (çünkü böyle bir anahtar sözcük tek başına bir ifade olamaz). son notu

12.9.9 Await ifadeleri

12.9.9.1 Genel

await işleci, işlenenin temsil ettiği eşzamansız işlem tamamlanana kadar kapsayıcı eşzamansız işlevin değerlendirilmesini askıya almak için kullanılır.

await_expression
    : 'await' unary_expression
    ;

Await_expression yalnızca bir asenkron işlevin gövdesinde (§15.14) kullanılabilir. En yakın kapsayıcı zaman uyumsuz işlevde, bu yerlerde bir await_expression bulunmamalıdır:

  • İç içe (zaman uyumsuz olmayan) anonim işlevin içinde
  • bir lock_statement bloğunun içinde
  • Anonim işlevde ifade ağacı türüne dönüştürme (§10.7.3)
  • Güvenli olmayan bir bağlamda

Not: await_expression, query_expression'ün çoğu yerinde kullanılamaz çünkü bunlar async olmayan lambda ifadelerini kullanmak üzere söz dizimsel olarak dönüştürülür. son notu

Zaman uyumsuz bir işlevin içinde await, available_identifier olarak kullanılmamalıdır; ancak @await açık tanımlayıcı olarak kullanılabilir. Bu nedenle, await_expressionile çeşitli tanımlayıcıları içeren ifadeler arasında söz dizimi belirsizliği yoktur. Zaman uyumsuz işlevlerin dışında await normal bir tanımlayıcı işlevi görür.

await_expression işleneni, göreviolarak adlandırılır. await_expression değerlendirildiğinde tamamlanmış veya tamamlanmamış olabilecek zaman uyumsuz bir işlemi temsil eder. await işlecinin amacı, beklenen görev tamamlanana kadar içeren asenkron işlevin yürütülmesini askıya almak ve ardından sonucunu elde etmektir.

12.9.9.2 Awaitable ifadeleri

bir await_expression görevininbeklenebilir olması gerekir. t ifadesi, aşağıdakilerden biri doğruysa beklenebilir:

  • t, derleme zamanı türü dynamic'dır.
  • t parametresiz ve tür parametresi olmayan GetAwaiter adlı erişilebilir bir örnek veya uzantı yöntemi ve aşağıdakilerin tümünün tutıldığı bir dönüş türü A vardır:
    • A arabirim System.Runtime.CompilerServices.INotifyCompletion uygular (bundan sonra kısa INotifyCompletion olarak bilinir)
    • A, IsCompleted türünde erişilebilir, okunabilir bir örnek özelliği bool sahiptir
    • A parametresiz ve tür parametresi olmayan GetResult erişilebilir bir örnek yöntemi vardır

GetAwaiter yönteminin amacı, görev için bir bekletici elde etmektir. await ifadesi için tür A, awaiter türü olarak adlandırılır.

IsCompleted özelliğinin amacı, görevin zaten tamamlanmış olup olmadığını belirlemektir. Bu durumda değerlendirmeyi askıya almanız gerekmez.

INotifyCompletion.OnCompleted yönteminin amacı göreve bir "devamlılık" eklemektir; yani, görev tamamlandıktan sonra çağrılacak bir temsilci (System.Actiontüründe).

GetResult yönteminin amacı, tamamlandıktan sonra görevin sonucunu elde etmektir. Bu sonuç, muhtemelen bir sonuç değeri ile başarılı bir şekilde tamamlanabilir veya GetResult yöntemi tarafından ortaya atılan bir istisna olabilir.

12.9.9.3 Await ifadelerinin sınıflandırması

await t ifadesi, (t).GetAwaiter().GetResult()ifadesiyle aynı şekilde sınıflandırılır. Bu nedenle, GetResult dönüş türü voidise, await_expression hiçbir şey olarak sınıflandırılır. void T olmayan bir dönüş türüne sahipse, await_expressionTtüründe bir değer olarak sınıflandırılır.

12.9.9.4 Await ifadelerinin çalışma zamanı değerlendirmesi

Çalışma zamanında, await t ifadesi aşağıdaki gibi değerlendirilir:

  • Awaiter a, (t).GetAwaiter()ifadesi değerlendirilerek elde edilir.
  • boolifadesi değerlendirilerek b(a).IsCompleted elde edilir.
  • b false ise değerlendirme, a arabirimi System.Runtime.CompilerServices.ICriticalNotifyCompletion uygulayıp uygulamadığına bağlıdır (bundan sonra kısalık için ICriticalNotifyCompletion olarak bilinir). Bu denetim bağlama zamanında yapılır; örneğin, adynamicderleme zamanı türüne sahipse çalışma zamanında ve aksi takdirde derleme zamanında. Yeniden sağlama temsilcisini (r) gösterelim:
    • a ICriticalNotifyCompletiongerçekleştirmezse ((a) as INotifyCompletion).OnCompleted(r) ifadesi değerlendirilir.
    • a ICriticalNotifyCompletionuygularsa, ((a) as ICriticalNotifyCompletion).UnsafeOnCompleted(r) ifadesi değerlendirilir.
    • Değerlendirme daha sonra askıya alınır ve kontrol, zaman uyumsuz işlevin anlık çağıranına geri döndürülür.
  • Ya hemen sonra (btrueise) ya da daha sonra yeniden başlatma temsilcisi çağrıldığında (bfalseise), ifade (a).GetResult() değerlendirilir. Bir değer döndürürse, bu değer await_expressionsonucudur. Aksi takdirde sonuç hiçbir şey değildir.

Bir awaiter'ın INotifyCompletion.OnCompleted ve ICriticalNotifyCompletion.UnsafeOnCompleted arabirim yöntemlerini uygulaması, temsilci r'nin en fazla bir kez çağrılmasıyla sonuçlanmalıdır. Aksi takdirde, kapsayan zaman uyumsuz işlevinin davranışı belirsizdir.

12.10 Aralık işleci

işleci .., aralık işleci olarak adlandırılır.

range_expression
    : unary_expression
    | unary_expression? '..' unary_expression?
    ;

Önceden tanımlanmış aralık işleci:

Range operator ..(Index x, Index y);

Aralık işleci aşırı yüklenemez (§12.4.3).

Tüm aralık ifadeleri formuna x..ysahip olarak değerlendirilir ve burada:

  • x varsa sol işlenendir; aksi takdirde ifade 0; ve
  • y varsa doğru işlenendir, aksi takdirde ifadesidir ^0.

İşlemin sonucu, ifadenin sonucuna eşdeğer bir Range (§18.3) değerdir:

new Range(x, y)

Bir aralık ifadesindeki işlenenlerden biri veya her ikisi de derleme zamanı türüne dynamicsahipse, ifade dinamik olarak bağlıdır (§12.3.3). Sonucun derleme zamanı türü her zaman Rangeolur.

Aralık işlecinin kaldırılmış (§12.4.8) biçimi de önceden tanımlanmıştır.

Aralık işleci ilişkilendirilemez (§12.4.2).

12.11 Anahtar ifadesi

switch_expression ifade bağlamında benzer semantikler sağlarswitch.

switch_expression
    : range_expression
    | switch_expression 'switch' '{' switch_expression_arms? '}'
    ;

switch_expression_arms
    : switch_expression_arm (',' switch_expression_arm)* ','?
    ;

switch_expression_arm
    : pattern case_guard? '=>' switch_expression_arm_expression
    ;

switch_expression_arm_expression
    : expression
    ;

Anahtar ifadenin switch_expression_arm her switch_expression_arm_expression örtük bir dönüştürme varsa, anahtar ifadeden türe T bir anahtar ifadesi dönüştürmesi (T) vardır.

Anahtar ifadesi bir anahtar ifade dönüştürmeye tabi değilse,

  • switch_expression türü, böyle bir tür varsa switch_expression_arm switch_expression_arm_expression en iyi ortak tür olan §12.6.3.16) türüdür ve her switch_expression_arm_expression örtük olarak bu türe dönüştürülebilir.
  • Böyle bir tür yoksa bu bir hatadır.

Önceki bir desen ve koruma her zaman eşleşeceği için bazı switch_expression_arm deseninin sonucu etkileyememesi bir hatadır.

Girdisinin her değeri switch ifadesinin en az bir kolu tarafından işlenirse, switch ifadesinin kapsamlı olduğu söylenir. Bir anahtar ifadesi kapsamlı değilse derleyici bir uyarı üretecektir. Çalışma zamanında, switch_expression sonucu, switch_expression sol tarafındaki ifadenin switch_expression_arm deseni ile eşleşdiği ve varsa switch_expression_arm case_guard değerlendirdiği ilk switch_expression_arm ifadesinin değeridir.true Böyle bir switch_expression_arm yoksa, switch_expression özel durumun System.InvalidOperationException bir örneğini (veya bundan türetilen bir sınıfı) oluşturur.

Örnek: Aşağıdaki, çevrimiçi haritadaki görsel yol tariflerini temsil eden bir sabit listesi değerlerini ilgili kardinal yol tariflerine dönüştürür:

static Orientation ToOrientation(Direction direction) => direction switch
{
    Direction.Up    => Orientation.North,
    Direction.Right => Orientation.East,
    Direction.Down  => Orientation.South,
    Direction.Left  => Orientation.West,
    _ => throw new ArgumentOutOfRangeException(direction.ToString()),
};

public enum Direction
{
    Up,
    Down,
    Right,
    Left
}

public enum Orientation
{
    North,
    South,
    East,
    West
}

son örnek

12.12 Aritmetik işleçler

12.12.1 Genel

*, /, %, +ve - işleçleri aritmetik işleçler olarak adlandırılır.

multiplicative_expression
    : switch_expression
    | multiplicative_expression '*' switch_expression
    | multiplicative_expression '/' switch_expression
    | multiplicative_expression '%' switch_expression
    ;

additive_expression
    : multiplicative_expression
    | additive_expression '+' multiplicative_expression
    | additive_expression '-' multiplicative_expression
    ;

Aritmetik bir operatörün operandi derleme zamanında dynamictüründeyse, ifade dinamik olarak bağlanır (§12.3.3). Bu durumda, ifadenin derleme zamanı türü dynamicve aşağıda açıklanan çözümleme, derleme zamanı türü dynamicolan işlenenlerin çalışma zamanı türü kullanılarak çalışma zamanında gerçekleşir.

12.12.2 Çarpma işleci

form x * yşeklinde bir işlem için, belirli bir operatör uygulamasını seçmek amacıyla, ikili operatör yükleme çözümü (§12.4.5) uygulanır. Operandlar, seçilen operatörün parametre türlerine dönüştürülür ve sonucun türü operatörün dönüş türüdür.

Önceden tanımlanmış çarpma işleçleri aşağıda listelenmiştir. Tüm işleçler x ve yürününü hesaplarlar.

  • Tamsayı çarpması:

    int operator *(int x, int y);
    uint operator *(uint x, uint y);
    long operator *(long x, long y);
    ulong operator *(ulong x, ulong y);
    

    checked bağlamında, ürün sonuç türü kapsamında değilse, bir System.OverflowException atılır. unchecked bağlamında taşmalar raporlanmaz ve sonuç türü aralığının dışındaki kayda değer yüksek sıralı bitler görmezden gelinir.

  • Kayan nokta çarpması:

    float operator *(float x, float y);
    double operator *(double x, double y);
    

    Ürün, IEC 60559 aritmetik kurallarına göre hesaplanır. Aşağıdaki tabloda sıfır olmayan sonlu değerlerin, sıfırların, sonsuzların ve NaN'lerin olası tüm birleşimlerinin sonuçları listelenmiştir. Tabloda, x ve y pozitif sonlu değerlerdir. z, en yakın temsil edilebilir değere yuvarlanmış x * ysonucudur. Sonucun büyüklüğü hedef tür için çok büyükse, z sonsuzdur. Yuvarlama nedeniyle, z veya x sıfır olmasa bile y sıfır olabilir.

    +y -y +0 -0 +∞ -∞ NaN
    +x +z -z +0 -0 +∞ -∞ NaN
    -x -z +z -0 +0 -∞ +∞ NaN
    +0 +0 -0 +0 -0 NaN NaN NaN
    -0 -0 +0 -0 +0 NaN NaN NaN
    +∞ +∞ -∞ NaN NaN +∞ -∞ NaN
    -∞ -∞ +∞ NaN NaN -∞ +∞ NaN
    NaN NaN NaN NaN NaN NaN NaN NaN

    (Aksi belirtilmediği durumlar dışında, §12.12.2§12.12.6'daki kayan nokta tablolarında "+" kullanımı değerin pozitif olduğu, "-" kullanımının değerin negatif olduğu, işaret olmaması ise değerin pozitif veya negatif olabileceği ya da işareti (NaN) olmadığı anlamına gelir.)

  • Ondalık çarpma:

    decimal operator *(decimal x, decimal y);
    

    Elde edilen değerin büyüklüğü ondalık biçimde gösteremeyecek kadar büyükse, bir System.OverflowException hatası meydana gelir. Yuvarlama nedeniyle, işlenenlerden hiçbiri sıfır olmasa bile sonuç sıfır olabilir. Herhangi bir yuvarlamadan önce sonucun ölçeği, iki işlenenin ölçeklerinin toplamıdır. Ondalık çarpma, System.Decimaltüründeki çarpma işlecinin kullanılmasıyla eşdeğerdir.

Yukarıda tanımlanan kaldırılmamış önceden tanımlanmış çarpma işleçlerinin kaldırılmış (§12.4.8) formları da önceden tanımlanmıştır.

12.12.3 Bölme işleci

form x / yşeklinde bir işlem için, belirli bir operatör uygulamasını seçmek amacıyla, ikili operatör yükleme çözümü (§12.4.5) uygulanır. Operandlar, seçilen operatörün parametre türlerine dönüştürülür ve sonucun türü operatörün dönüş türüdür.

Önceden tanımlanmış bölme işleçleri aşağıda listelenmiştir. İşleçlerin tümü x ve y'nin bölümünü hesaplar.

  • Tamsayı bölme:

    int operator /(int x, int y);
    uint operator /(uint x, uint y);
    long operator /(long x, long y);
    ulong operator /(ulong x, ulong y);
    

    Eğer sağ işlenenin değeri sıfırsa, bir System.DivideByZeroException fırlatılır.

    Bölme işlemi, sonucu sıfıra doğru yuvarlar. Bu nedenle sonucun mutlak değeri, iki işlenenin bölümünün mutlak değerinden küçük veya buna eşit olabilecek en büyük tamsayıdır. sonuç, iki işlenen aynı işarete sahip olduğunda sıfır veya pozitif, iki işlenen karşıt işaretlere sahip olduğunda sıfır veya negatiftir.

    Sol işlenen en küçük temsil edilebilir int veya long değeriyse ve sağ işlenen –1 ise, taşma meydana gelir. checked bağlamında, bu bir System.ArithmeticException (veya alt sınıfının) atılmasına neden olur. unchecked bir bağlamda, bir System.ArithmeticException (veya bir alt sınıfı) fırlatılıp fırlatılmayacağı veya taşmanın bildirilmeden kalıp kalmayacağı ve bu durumda elde edilen değerin sol işlenenin değeri olacağı uygulama tarafından belirlenir.

  • Kayan nokta bölme:

    float operator /(float x, float y);
    double operator /(double x, double y);
    

    Oran, IEC 60559 aritmetik fiili kurallarına göre hesaplanır. Aşağıdaki tabloda sıfır olmayan sonlu değerlerin, sıfırların, sonsuzların ve NaN'lerin olası tüm birleşimlerinin sonuçları listelenmiştir. Tabloda, x ve y pozitif sonlu değerlerdir. z, en yakın temsil edilebilir değere yuvarlanmış x / ysonucudur.

    +y -y +0 -0 +∞ -∞ NaN
    +x +z -z +∞ -∞ +0 -0 NaN
    -x -z +z -∞ +∞ -0 +0 NaN
    +0 +0 -0 NaN NaN +0 -0 NaN
    -0 -0 +0 NaN NaN -0 +0 NaN
    +∞ +∞ -∞ +∞ -∞ NaN NaN NaN
    -∞ -∞ +∞ -∞ +∞ NaN NaN NaN
    NaN NaN NaN NaN NaN NaN NaN NaN
  • Ondalık bölme:

    decimal operator /(decimal x, decimal y);
    

    Eğer sağ işlenenin değeri sıfırsa, bir System.DivideByZeroException fırlatılır. Elde edilen değerin büyüklüğü ondalık biçimde gösteremeyecek kadar büyükse, bir System.OverflowException hatası meydana gelir. Yuvarlama nedeniyle, ilk operatör sıfır olmasa bile sonuç sıfır olabilir. Herhangi bir yuvarlamadan önce sonucun ölçeği, tercih edilen ölçeğe en yakın ölçektir ve sonucu tam sonucla eşit olarak korur. Tercih edilen ölçek, x ölçeğinin, yölçeğinin çıkarılmasıyla elde edilendir.

    Ondalık bölme, System.Decimaltüründeki bölme işlecinin kullanılmasıyla eşdeğerdir.

Yukarıda tanımlanan kaldırılmamış önceden tanımlı bölme operatörlerinin yükseltilmiş (§12.4.8) formları da yine önceden tanımlanmıştır.

12.12.4 Kalan işleci

form x % yşeklinde bir işlem için, belirli bir operatör uygulamasını seçmek amacıyla, ikili operatör yükleme çözümü (§12.4.5) uygulanır. Operandlar, seçilen operatörün parametre türlerine dönüştürülür ve sonucun türü operatörün dönüş türüdür.

Önceden tanımlanmış kalan işleçler aşağıda listelenmiştir. İşleçlerin tümü, x ile yarasındaki bölmenin geri kalanını hesaplar.

  • Kalan tamsayı:

    int operator %(int x, int y);
    uint operator %(uint x, uint y);
    long operator %(long x, long y);
    ulong operator %(ulong x, ulong y);
    

    x % y sonucu, x – (x / y) * ytarafından üretilen değerdir. y sıfırsa, bir System.DivideByZeroException fırlatılır.

    Sol işlenen en küçük int veya long değerse ve sağ işlenen –1ise, ancak ve ancak System.OverflowException bir istisna oluşturuyorsa bir x / y oluşturulur.

  • Kayan nokta kalanı:

    float operator %(float x, float y);
    double operator %(double x, double y);
    

    Aşağıdaki tabloda sıfır olmayan sonlu değerlerin, sıfırların, sonsuzların ve NaN'lerin olası tüm birleşimlerinin sonuçları listelenmiştir. Tabloda, x ve y pozitif sonlu değerlerdir. z, x % y sonucudur ve x – n * yolarak hesaplanır; burada n, x / y'den küçük veya buna eşit olan mümkün olan en büyük tamsayıdır. Geri kalanı hesaplamanın bu yöntemi, tamsayı işlenenleri için kullanılana benzer, ancak IEC 60559 tanımından farklıdır (nx / yen yakın tamsayıdır).

    +y -y +0 -0 +∞ -∞ NaN
    +x +z +z NaN NaN +x +x NaN
    -x -z -z NaN NaN -x -x NaN
    +0 +0 +0 NaN NaN +0 +0 NaN
    -0 -0 -0 NaN NaN -0 -0 NaN
    +∞ NaN NaN NaN NaN NaN NaN NaN
    -∞ NaN NaN NaN NaN NaN NaN NaN
    NaN NaN NaN NaN NaN NaN NaN NaN
  • Ondalık kalan:

    decimal operator %(decimal x, decimal y);
    

    Eğer sağ işlenenin değeri sıfırsa, bir System.DivideByZeroException fırlatılır. System.ArithmeticException (veya onun alt sınıfı) fırlatıldığında bunun uygulama tarafından nasıl tanımlandığı belirtilmiştir. Uyumlu bir uygulama, x % y özel durum oluşturmadığı her durumda x / y için özel durum oluşturmaz. Herhangi bir yuvarlamadan önce sonucun ölçeği, iki işlenenin ölçeklerinin daha büyüktür ve sıfır olmayan sonucun işareti xile aynıdır.

    Ondalık kalan, System.Decimaltürünün kalan işlecini kullanarak elde edilen sonuca eşdeğerdir.

    Not: Bu kurallar, tüm türler için sonucun hiçbir zaman sol operatörün karşıt işaretine sahip olmamasını sağlar. son notu

Kaldırılmamış önceden tanımlanmış kalan işleçlerin yukarıda tanımlanan kaldırılmış (§12.4.8) formları da önceden tanımlanmıştır.

12.12.5 Toplama işleci

form x + yşeklinde bir işlem için, belirli bir operatör uygulamasını seçmek amacıyla, ikili operatör yükleme çözümü (§12.4.5) uygulanır. Operandlar, seçilen operatörün parametre türlerine dönüştürülür ve sonucun türü operatörün dönüş türüdür.

Önceden tanımlanmış toplama işleçleri aşağıda listelenmiştir. Sayısal ve numaralandırma türleri için, önceden tanımlanmış toplama işleçleri iki işlenenin toplamını hesaplar. bir veya her iki işlenen stringtüründe olduğunda, önceden tanımlanmış toplama işleçleri işlenenlerin dize gösterimini birleştirir.

  • Tamsayı ekleme:

    int operator +(int x, int y);
    uint operator +(uint x, uint y);
    long operator +(long x, long y);
    ulong operator +(ulong x, ulong y);
    

    checked bağlamında, toplam sonuç türü aralığının dışındaysa, bir System.OverflowException atılır. unchecked bağlamında taşmalar raporlanmaz ve sonuç türü aralığının dışındaki kayda değer yüksek sıralı bitler görmezden gelinir.

  • Kayan nokta ekleme:

    float operator +(float x, float y);
    double operator +(double x, double y);
    

    Toplam, IEC 60559 aritmetik kurallarına göre hesaplanır. Aşağıdaki tabloda sıfır olmayan sonlu değerlerin, sıfırların, sonsuzların ve NaN'lerin olası tüm birleşimlerinin sonuçları listelenmiştir. Tabloda, x ve y sıfır olmayan sonlu değerlerdir ve zx + ysonucudur. x ve y aynı büyüklüğe ancak karşıt işaretlere sahipse, z pozitif sıfırdır. x + y hedef türünde temsil edilemeyecek kadar büyükse, zx + yile aynı işareti olan bir sonsuzdur.

    y +0 -0 +∞ -∞ NaN
    x z x x +∞ -∞ NaN
    +0 y +0 +0 +∞ –∞ NaN
    -0 y +0 -0 +∞ -∞ NaN
    +∞ +∞ +∞ +∞ +∞ NaN NaN
    -∞ -∞ -∞ -∞ NaN -∞ NaN
    NaN NaN NaN NaN NaN NaN NaN
  • Ondalık ekleme:

    decimal operator +(decimal x, decimal y);
    

    Elde edilen değerin büyüklüğü ondalık biçimde gösteremeyecek kadar büyükse, bir System.OverflowException hatası meydana gelir. Herhangi bir yuvarlamadan önce, sonucun ölçeği, iki işlenenin ölçeklerinden daha büyük olanıdır.

    Ondalık ekleme, System.Decimaltüründeki toplama işlecini kullanmaya eşdeğerdir.

  • Numaralandırma ekleme. Her bir numaralandırma türü, doğal olarak aşağıdaki önceden tanımlanmış işleçleri sağlamaktadır; burada E numaralandırma türü ve U ise E'nin temel aldığı türdür.

    E operator +(E x, U y);
    E operator +(U x, E y);
    

    Çalışma zamanında bu işleçler tam olarak (E)((U)x + (U)y) şeklinde değerlendirilir.

  • Dize birleştirme:

    string operator +(string x, string y);
    string operator +(string x, object y);
    string operator +(object x, string y);
    

    İkili + işlecinin bu aşırı yükleri dize birleştirme gerçekleştirir. Dize birleştirme işleneni nullise, yerine boş bir dize geçirilir. Aksi takdirde, herhangi birstring olmayan işlenen, ToStringtüründen devralınan sanal object yöntemi çağrılarak string gösterimine dönüştürülür. ToString nulldöndürürse, yerine boş bir dize gelir.

    Örnek:

    class Test
    {
        static void Main()
        {
            string s = null;
            Console.WriteLine("s = >" + s + "<");  // Displays s = ><
    
            int i = 1;
            Console.WriteLine("i = " + i);         // Displays i = 1
    
            float f = 1.2300E+15F;
            Console.WriteLine("f = " + f);         // Displays f = 1.23E+15
    
            decimal d = 2.900m;
            Console.WriteLine("d = " + d);         // Displays d = 2.900
       }
    }
    

    Açıklamalarda gösterilen çıkış, US-English sistemindeki tipik bir sonuçdur. Kesin çıkış, yürütme ortamının bölgesel ayarlarına bağlı olabilir. Dize birleştirme işleci her durumda aynı şekilde davranır, ancak yürütme sırasında örtük olarak çağrılan ToString yöntemleri bölgesel ayarlardan etkilenebilir.

    son örnek

    Dize birleştirme işlecinin sonucu, sol işlenenin karakterlerinden ve ardından sağ işlenenin karakterlerinden oluşan bir string. Dize birleştirme işleci hiçbir zaman null değeri döndürmez. Sonuç dizeyi oluşturmak için yeterli bellek yoksa bir System.OutOfMemoryException hatası meydana gelebilir.

  • Temsilci birleşimi. Her temsilci türü, D temsilci türü olarak aşağıdaki önceden tanımlanmış operatörü örtük bir şekilde sağlar:

    D operator +(D x, D y);
    

    İlk işlenen nullise, işlemin sonucu ikinci işlenenin değeridir (aynı zamanda nullolsa bile). Aksi takdirde, ikinci işlenen nullise, işlemin sonucu ilk işlenenin değeridir. Aksi takdirde, işlemin sonucu, ilk işlenenin çağrı listesindeki öğelerden ve ardından ikinci işlenenin çağrı listesindeki öğelerden oluşan yeni bir temsilci örneğidir. Diğer bir ifadeyle, sonuçta elde edilen temsilcinin çağrı listesi, iki işlemin çağrı listelerinin bir araya getirilmiş halidir.

    Not: Temsilci birleşimi örnekleri için bkz. §12.12.6 ve §21.6. System.Delegate bir temsilci türü olmadığından, + işleci bunun için tanımlanmamıştır. son not

Önceden tanımlanmış, kaldırılmamış toplama işleçlerinin yukarıda tanımlanan kaldırılmış (§12.4.8) formları da önceden tanımlanmıştır.

12.12.6 Çıkarma işleci

form x – yşeklinde bir işlem için, belirli bir operatör uygulamasını seçmek amacıyla, ikili operatör yükleme çözümü (§12.4.5) uygulanır. Operandlar, seçilen operatörün parametre türlerine dönüştürülür ve sonucun türü operatörün dönüş türüdür.

Önceden tanımlanmış çıkarma işleçleri aşağıda listelenmiştir. İşleçlerin tümü, y'den x'ı çıkarır.

  • Tamsayı çıkarma:

    int operator –(int x, int y);
    uint operator –(uint x, uint y);
    long operator –(long x, long y);
    ulong operator –(ulong x, ulong y
    

    checked bağlamında, fark sonuç türü aralığının dışındaysa, bir System.OverflowException atılır. unchecked bağlamında taşmalar raporlanmaz ve sonuç türü aralığının dışındaki kayda değer yüksek sıralı bitler görmezden gelinir.

  • Kayan nokta çıkarma:

    float operator –(float x, float y);
    double operator –(double x, double y);
    

    Fark, IEC 60559 aritmetik kurallarına göre hesaplanır. Aşağıdaki tabloda sıfır olmayan sonlu değerlerin, sıfırların, sonsuzların ve NaN'lerin olası tüm birleşimlerinin sonuçları listelenmiştir. Tabloda, x ve y sıfır olmayan sonlu değerlerdir ve zx – ysonucudur. x ve y eşitse, z pozitif sıfır olur. x – y hedef türünde temsil edilemeyecek kadar büyükse, zx – yile aynı işareti olan bir sonsuzdur.

    y +0 -0 +∞ -∞ NaN
    x z x x -∞ +∞ NaN
    +0 -y +0 +0 -∞ +∞ NaN
    -0 -y -0 +0 -∞ +∞ NaN
    +∞ +∞ +∞ +∞ NaN +∞ NaN
    -∞ -∞ -∞ -∞ -∞ NaN NaN
    NaN NaN NaN NaN NaN NaN NaN

    (Yukarıdaki tabloda, -y girdileri 'ün y anlamına gelir; bu, değerin negatif olduğu anlamına gelmez.)

  • Ondalık çıkarma:

    decimal operator –(decimal x, decimal y);
    

    Elde edilen değerin büyüklüğü ondalık biçimde gösteremeyecek kadar büyükse, bir System.OverflowException hatası meydana gelir. Herhangi bir yuvarlamadan önce, sonucun ölçeği, iki işlenenin ölçeklerinden daha büyük olanıdır.

    Ondalık çıkarma, System.Decimaltüründeki çıkarma işlecinin kullanılmasıyla eşdeğerdir.

  • Numaralandırma çıkarma. Her sabit listesi türü, E sabit listesi türü ve UE'nin altında yatan türü olmak üzere aşağıdaki önceden tanımlanmış işleci dolaylı olarak sağlar:

    U operator –(E x, E y);
    

    Bu işleç tam olarak (U)((U)x – (U)y)olarak değerlendirilir. Başka bir deyişle, işleç x ve ysıra değerleri arasındaki farkı hesaplar ve sonucun türü numaralandırmanın temel türüdür.

    E operator –(E x, U y);
    

    Bu işleç tam olarak (E)((U)x – y)olarak değerlendirilir. Başka bir deyişle, işleç, numaralandırmanın temel türünden bir değeri çıkararak bir numaralandırma değeri elde eder.

  • Temsilcinin kaldırılması. Her temsilci türü, D temsilci türü olarak aşağıdaki önceden tanımlanmış operatörü örtük bir şekilde sağlar:

    D operator –(D x, D y);
    

    Semantik aşağıdaki gibidir:

    • İlk operand nullise, işlemin sonucu nullolur.
    • Aksi takdirde, ikinci işlenen nullise, işlemin sonucu ilk işlenenin değeridir.
    • Aksi takdirde, her iki işlenen de boş olmayan çağırma listelerini (§21.2) temsil eder.
      • Listeler, temsilci eşitlik işleci (§12.14.9) tarafından belirlenen eşitliği karşılaştırırsa, işlemin sonucu olur null.
      • Aksi takdirde, işlemin sonucu, ikinci işlenenin listesinin ilk işlenenlerin alt listesi olması koşuluyla, ikinci işlenenin girdilerinin kaldırıldığı ilk işlenen listesinden oluşan yeni bir çağırma listesidir. (Alt liste eşitliğini belirlemek için, karşılık gelen girdiler temsilci eşitlik işleciyle karşılaştırılır.) İkinci işlenenin listesi, ilk işlenenin listesindeki bitişik girdilerin birden çok alt listesiyle eşleşiyorsa, bitişik girdilerin eşleşen son alt listesi kaldırılır.
      • Aksi takdirde, işlemin sonucu sol operantın değeridir.

    İşlenenlerin (varsa) listelerinden hiçbiri işlem sırasında değiştirilmez.

    Örnek:

    delegate void D(int x);
    
    class C
    {
        public static void M1(int i) { ... }
        public static void M2(int i) { ... }
    }
    
    class Test
    {
        static void Main()
        {
            D cd1 = new D(C.M1);
            D cd2 = new D(C.M2);
            D list = null;
    
            list = null - cd1;                             // null
            list = (cd1 + cd2 + cd2 + cd1) - null;         // M1 + M2 + M2 + M1
            list = (cd1 + cd2 + cd2 + cd1) - cd1;          // M1 + M2 + M2
            list = (cd1 + cd2 + cd2 + cd1) - (cd1 + cd2);  // M2 + M1
            list = (cd1 + cd2 + cd2 + cd1) - (cd2 + cd2);  // M1 + M1
            list = (cd1 + cd2 + cd2 + cd1) - (cd2 + cd1);  // M1 + M2
            list = (cd1 + cd2 + cd2 + cd1) - (cd1 + cd1);  // M1 + M2 + M2 + M1
            list = (cd1 + cd2 + cd2 + cd1) - (cd1 + cd2 + cd2 + cd1);  // null
        }
    }
    

    son örnek

Yukarıda tanımlanan standart tanımlanmış çıkarma işleçlerinin kaldırılmış (§12.4.8) formları da standart olarak tanımlanmıştır.

12.13 Shift işleçleri

<< ve >> işleçleri, bit kaydırma işlemleri gerçekleştirmek için kullanılır.

shift_expression
    : additive_expression
    | shift_expression '<<' additive_expression
    | shift_expression right_shift additive_expression
    ;

bir shift_expression işleneni dynamicderleme zamanı türüne sahipse, ifade dinamik olarak bağlıdır (§12.3.3). Bu durumda, ifadenin derleme zamanı türü dynamicve aşağıda açıklanan çözümleme, derleme zamanı türü dynamicolan işlenenlerin çalışma zamanı türü kullanılarak çalışma zamanında gerçekleşir.

x << count veya x >> countformunda bir işlem için, belirli bir işlemci uygulamasını seçmek için ikili işlemci aşırı yükleme çözümü (§12.4.5) uygulanır. Operandlar, seçilen operatörün parametre türlerine dönüştürülür ve sonucun türü operatörün dönüş türüdür.

Aşırı yüklenmiş bir vardiya işleci bildirilirken, ilk işlenenin türü her zaman işleç bildirimini içeren sınıf veya yapı olacaktır ve ikinci işlenenin türü her zaman intolacaktır.

Önceden tanımlanmış vardiya işleçleri aşağıda listelenmiştir.

  • Sola kaydır:

    int operator <<(int x, int count);
    uint operator <<(uint x, int count);
    long operator <<(long x, int count);
    ulong operator <<(ulong x, int count);
    

    << işleci, aşağıda açıklandığı gibi hesaplanan bit sayısı kadar x'i sola kaydırır.

    x sonuç türü aralığının dışındaki yüksek sıralı bitler atılır, kalan bitler sola kaydırılır ve düşük sıralı boş bit konumları sıfır olarak ayarlanır.

  • Sağa kaydır:

    int operator >>(int x, int count);
    uint operator >>(uint x, int count);
    long operator >>(long x, int count);
    ulong operator >>(ulong x, int count);
    

    >> işleci, aşağıda açıklandığı gibi hesaplanan bir bit sayısı kadar x'i sağa kaydırır.

    x int veya longtüründe olduğunda, düşük sıralı x bitleri atılır, kalan bitler sağa kaydırılır ve x negatif değilse yüksek sıralı boş bit konumları sıfıra ayarlanır ve x negatifse bir olarak ayarlanır.

    x uint veya ulongtüründe olduğunda, düşük sıralı x bitleri atılır, kalan bitler sağa kaydırılır ve yüksek sıralı boş bit konumları sıfır olarak ayarlanır.

Önceden tanımlanmış işleçler için kaydıracak bit sayısı aşağıdaki gibi hesaplanır:

  • x türü int veya uintolduğunda, vardiya sayısı düşük sıralı beş bit counttarafından verilir. Başka bir deyişle, vardiya sayısı count & 0x1F'dan hesaplanır.
  • x türü long veya ulongolduğunda, vardiya sayısı alt sıralı altı bit counttarafından verilir. Başka bir deyişle, vardiya sayısı count & 0x3F'dan hesaplanır.

Sonuçta elde edilen vardiya sayısı sıfırsa, shift işleçleri yalnızca xdeğerini döndürür.

Shift işlemleri hiçbir zaman taşmalara neden olmaz ve kontrollü ve kontrolsüz bağlamlarda aynı sonuçları üretir.

>> işlecinin sol işleneni imzalı bir tamsayı türünde olduğunda, işleç, işlenenin en anlamlı bitinin (işaret biti) değerinin en yüksek sıradaki boş bit konumlarına yayıldığı bir aritmetik sağa kaydırma işlemi gerçekleştirir. >> işlecinin sol operatörü işaretsiz bir tamsayı türündeyse, işleç sağa doğru bir mantıksal kaydırma yapar ve bu kaydırmada yüksek sıralı boş bit konumları her zaman sıfır olarak ayarlanır. İşlenen türünden çıkarılanın ters işlemini gerçekleştirmek için, açık dönüşümler kullanılabilir.

Örnek: xinttüründe bir değişkense, işlem unchecked ((int)((uint)x >> y))x'in sağındaki mantıksal kaydırmayı gerçekleştirir. son örnek

Yukarıda tanımlanan yüklememiş önceden tanımlanmış vardiya işleçlerinin yüklenmiş (§12.4.8) formları da önceden tanımlanmıştır.

12.14 İlişkisel ve tür testi işleçleri

12.14.1 Genel

==, !=, <, >, <=, >=, isve as işleçleri ilişkisel ve tür testi işleçleri olarak adlandırılır.

relational_expression
    : shift_expression
    | relational_expression '<' shift_expression
    | relational_expression '>' shift_expression
    | relational_expression '<=' shift_expression
    | relational_expression '>=' shift_expression
    | relational_expression 'is' type
    | relational_expression 'is' pattern
    | relational_expression 'as' type
    ;

equality_expression
    : relational_expression
    | equality_expression '==' relational_expression
    | equality_expression '!=' relational_expression
    ;

Not: işlecinin sağ işleneni için yapılan aramanın önce türü olarak, ardından birden çok belirteci kapsayan ifadesi olarak test edilmesi gerekir. İşlenenin bir ifade olması durumunda, desen ifadesinin en az shift_expression kadar yüksek bir önceliğe sahip olması gerekir. son notu

Not: türü ilesağ tarafındaki relational_expressionbir is içindeki constant_pattern arasında dil bilgisi belirsizliği vardır; nitelenmiş tanımlayıcının geçerli bir ayrıştırma olabilir. Böyle bir durumda, yalnızca bir tür olarak bağlanamazsa (dilin önceki sürümleriyle uyumluluk için), bulunan ilk şey (sabit veya tür olmalıdır) olarak çözümlenir. Bu belirsizlik yalnızca böyle bir ifadenin sağ tarafında bulunur.

İşleç is§12.14.12as ve işleç ise §12.14.13'te açıklanmıştır.

, , , , ve işleçlerikarşılaştırma işleçleri .

default_literal (§12.8.21) bir <, >, <=veya >= işlecinin işleneni olarak kullanılıyorsa derleme zamanı hatası oluşur. bir default_literal bir == veya != işlecinin her iki işleneni olarak kullanılırsa, derleme zamanı hatası oluşur. Eğer bir default_literal, is veya as işlecinin sol işleneni olarak kullanılırsa, derleme zamanı hatası meydana gelir.

Karşılaştırma işlecinin işleneni dynamic derleme zamanı türüne sahipse, ifade dinamik olarak bağlanır (§12.3.3). Bu durumda ifadenin derleme zamanı türü dynamic'dir ve aşağıda açıklanan çözüm, derleme zamanı türü dynamicolan işlenenlerin çalışma zamanı türü kullanılarak, çalışma zamanında gerçekleşecektir.

x «op» ybiçiminin bir işlemi için , burada «op» karşılaştırma işlecidir, belirli bir işleç uygulamasını seçmek için aşırı yükleme çözümlemesi (§12.4.5) uygulanır. Operandlar, seçilen operatörün parametre türlerine dönüştürülür ve sonucun türü operatörün dönüş türüdür. Bir eşitlik_ifadesi her iki işleneni de null sabit bir değer olduğunda, aşırı yük çözümlemesi yapılmaz ve operatörün true veya falseolmasına göre ifade == veya != sabit bir değere değerlendirilir.

Önceden tanımlanmış karşılaştırma işleçleri aşağıdaki alt öğelerde açıklanmıştır. Önceden tanımlanmış tüm karşılaştırma işleçleri, aşağıdaki tabloda açıklandığı gibi bool türünün sonucunu döndürür.

İşlem Sonuç
x == y true, xy'ye eşitse, değilse false
x != y true, x'ye eşit değilse y, aksi halde false
x < y true x'den küçükse y, aksi halde false
x > y true x'den büyükse y, aksi takdirde false
x <= y true xdeğerinden küçük veya buna eşitse y, aksi takdirde false
x >= y true xdeğerinden büyük veya buna eşitse y, aksi halde false

12.14.2 Tamsayı karşılaştırma işleçleri

Önceden tanımlanmış tamsayı karşılaştırma işleçleri şunlardır:

bool operator ==(int x, int y);
bool operator ==(uint x, uint y);
bool operator ==(long x, long y);
bool operator ==(ulong x, ulong y);

bool operator !=(int x, int y);
bool operator !=(uint x, uint y);
bool operator !=(long x, long y);
bool operator !=(ulong x, ulong y);

bool operator <(int x, int y);
bool operator <(uint x, uint y);
bool operator <(long x, long y);
bool operator <(ulong x, ulong y);

bool operator >(int x, int y);
bool operator >(uint x, uint y);
bool operator >(long x, long y);
bool operator >(ulong x, ulong y);

bool operator <=(int x, int y);
bool operator <=(uint x, uint y);
bool operator <=(long x, long y);
bool operator <=(ulong x, ulong y);

bool operator >=(int x, int y);
bool operator >=(uint x, uint y);
bool operator >=(long x, long y);
bool operator >=(ulong x, ulong y);

Bu işleçlerin her biri iki tamsayı işleneninin sayısal değerlerini karşılaştırır ve belirli bir ilişkinin bool mi yoksa truemi olduğunu gösteren bir false değeri döndürür.

Yukarıda tanımlanan kaldırılmamış önceden tanımlanmış tamsayı karşılaştırma işleçlerinin lifted (§12.4.8) formları da önceden tanımlanmıştır.

12.14.3 Kayan nokta karşılaştırma işleçleri

Önceden tanımlanmış kayan nokta karşılaştırma işleçleri şunlardır:

bool operator ==(float x, float y);
bool operator ==(double x, double y);

bool operator !=(float x, float y);
bool operator !=(double x, double y);

bool operator <(float x, float y);
bool operator <(double x, double y);

bool operator >(float x, float y);
bool operator >(double x, double y);

bool operator <=(float x, float y);
bool operator <=(double x, double y);

bool operator >=(float x, float y);
bool operator >=(double x, double y);

İşleçler, işlenenleri IEC 60559 standardının kurallarına göre karşılaştırır.

İşlenenlerden biri NaN ise, sonuç falseiçin !=, diğer tüm işleçler için true olur. herhangi iki işlenen için x != y her zaman !(x == y)ile aynı sonucu verir. Ancak, işlenenlerden biri veya her ikisi de NaN olduğunda, <, >, <= ve >= operatörleri, karşı operatörün mantıksal olumsuzlaması ile aynı sonuçları üretmez.

Örnek: x ve y biri NaN ise x < yfalse, !(x >= y)true. son örnek

İşlenenlerden hiçbiri NaN olmadığında, işleçler iki kayan nokta işleneninin değerlerini sıralamaya göre karşılaştırır

–∞ < –max < ... < –min < –0.0 == +0.0 < +min < ... < +max < +∞

burada min ve max, verilen kayan nokta biçiminde temsil edilebilen en küçük ve en büyük pozitif sonlu değerlerdir. Bu sıralamanın önemli etkileri şunlardır:

  • Negatif ve pozitif sıfırlar eşit kabul edilir.
  • Negatif sonsuz, diğer tüm değerlerden daha az, ancak başka bir negatif sonsuzluğa eşit olarak kabul edilir.
  • Pozitif sonsuzluk diğer tüm değerlerden daha büyük olarak kabul edilir, ancak başka bir pozitif sonsuzluğa eşittir.

Kaldırılmamış önceden tanımlanmış kayan nokta karşılaştırma işleçlerinin yukarıda tanımlanan formları da kaldırılmış (§12.4.8) olarak önceden tanımlanmıştır.

12.14.4 Ondalık karşılaştırma işleçleri

Önceden tanımlanmış ondalık karşılaştırma işleçleri şunlardır:

bool operator ==(decimal x, decimal y);
bool operator !=(decimal x, decimal y);
bool operator <(decimal x, decimal y);
bool operator >(decimal x, decimal y);
bool operator <=(decimal x, decimal y);
bool operator >=(decimal x, decimal y);

Bu işleçlerin her biri iki ondalık işlenenin sayısal değerlerini karşılaştırır ve belirli bir ilişkinin bool veya trueolduğunu belirten bir false değeri döndürür. Her ondalık karşılaştırma, System.Decimaltüründe karşılık gelen ilişkisel veya eşitlik işlecinin kullanılmasıyla eşdeğerdir.

Yukarıda tanımlanmış kaldırılmamış önceden tanımlı ondalık karşılaştırma işleçlerinin kaldırılmış (§12.4.8) formları da önceden tanımlanmıştır.

12.14.5 Boole eşitliği işleçleri

Önceden tanımlanmış Boole eşitliği işleçleri şunlardır:

bool operator ==(bool x, bool y);
bool operator !=(bool x, bool y);

Eğer hem == hem de truex ise veya hem y hem de truexise, y sonucu false olur. Aksi takdirde sonuç false.

Eğer hem != hem de falsex ise veya hem y hem de truexise, y sonucu false olur. Aksi takdirde sonuç true. İşlenenler booltüründe olduğunda, != işleci ^ işleciyle aynı sonucu verir.

Yukarıda tanımlanan kaldırılmamış önceden tanımlanmış Boole eşitlik operatörlerin lifted (§12.4.8) formları da aynı şekilde önceden tanımlanmıştır.

12.14.6 Numaralandırma karşılaştırma işleçleri

Her numaralandırma türü örtük olarak aşağıdaki önceden tanımlanmış karşılaştırma işleçlerini sağlar

bool operator ==(E x, E y);
bool operator !=(E x, E y);

bool operator <(E x, E y);
bool operator >(E x, E y);
bool operator <=(E x, E y);
bool operator >=(E x, E y);

x «op» y'ı değerlendirmenin sonucu, x ve y'nin Etemel türüne sahip bir numaralandırma türü olan U ifadeleri olduğu ve «op»'un karşılaştırma operatörlerinden biri olduğu durumda ((U)x) «op» ((U)y)'ü değerlendirmekle tam olarak aynıdır. Başka bir deyişle, numaralandırma türü karşılaştırma işleçleri yalnızca iki işlenenin temel integral değerlerini karşılaştırır.

Yukarıda tanımlanan kaldırılmamış önceden tanımlanmış numaralandırma karşılaştırma işleçlerinin yükseltilmiş (§12.4.8) formları da önceden tanımlanmıştır.

12.14.7 Başvuru türü eşitlik işleçleri

Her sınıf türü C örtük olarak aşağıdaki önceden tanımlanmış başvuru türü eşitlik işleçlerini sağlar:

bool operator ==(C x, C y);
bool operator !=(C x, C y);

C için önceden tanımlanmış eşitlik işleçleri yoksa (örneğin, Cstring veya System.Delegateolduğunda).

İşleçler, iki referansın eşitlik veya eşitsizlik açısından karşılaştırılmasının sonucunu döndürür. operator ==, yalnızca true ve x aynı örneğe başvuruyorsa ya da her ikisi de yise null döndürür. Öte yandan, operator !=, yalnızca aynı işlenenlere sahip trueoperator ==döndürecekse false döndürür.

Normal uygulanabilirlik kurallarına (§12.6.4.2) ek olarak, önceden tanımlanmış başvuru türü eşitlik işleçleri uygulanabilir olması için aşağıdakilerden birini gerektirir:

  • İki işlenen de reference_type veya nullsabit değeri olduğu bilinen bir tipin değeridir. Ayrıca, bir işlenenden diğer işlenenin türüne bir kimlik veya açık referans dönüşümü (§10.3.5) vardır.
  • İşlenenlerden biri sabit null, diğer işlenen ise T bir değer türü olduğu bilinmeyen ve değer türü kısıtlamasına sahip olmayan bir T olduğu türünde bir değerdir.
    • Çalışma zamanında T null atanamaz bir değer türüyse, =='in sonucu false ve !='ün sonucu trueolur.
    • Çalışma zamanında T null atanabilir bir değer türüyse, sonuç (HasValue) bölümünde açıklandığı gibi işlenenin özelliğinden hesaplanır.
    • Çalışma zamanında T bir referans tipi ise, operand trueise sonuç null ve aksi takdirde false.

Bu koşullardan biri doğru değilse, bağlama zamanı hatası oluşur.

Not: Bu kuralların önemli etkileri şunlardır:

  • Bağlama zamanında farklı olduğu bilinen iki başvuruyu karşılaştırmak için önceden tanımlanmış başvuru türü eşitlik işleçlerinin kullanılması bağlama zamanı hatasıdır. Örneğin, işlenenlerin bağlama zamanı türleri iki sınıf türüyse ve hiçbiri diğerinden türetilmiyorsa, iki işlenenin aynı nesneye başvurması imkansız olur. Bu nedenle, işlem bağlama zamanı hatası olarak kabul edilir.
  • Önceden tanımlanmış başvuru türü eşitlik işleçleri, değer türü işlenenlerinin karşılaştırılmalarına izin vermez (tür parametrelerinin özel olarak işlenen nullile karşılaştırılması dışında).
  • Önceden tanımlanmış başvuru türü eşitlik operatörleri hiçbir zaman kutulanmaz. Yeni tahsis edilen kutulanmış örneklere yapılan referanslar diğer tüm referanslardan farklı olacağından, böyle kutulama işlemleri gerçekleştirmek anlamsızdır.

formunun x == y ya da x != yşeklinde olan bir işlemi için, geçerli kullanıcı tanımlı operator == veya operator != varsa, işleç aşırı yükleme çözümleme kuralları (§12.4.5) yukarıda tanımlanmış başvuru türü eşitlik işleci yerine bu işleci seçer. objecttürüne açıkça dönüştürerek işlenenlerden birini veya her ikisini de tanımlı referans türü eşitliği işlecini seçmek her zaman mümkündür.

son notu

Örnek: Aşağıdaki örnek, kısıtlanmamış türdeki parametre türünün bağımsız değişkeninin nullolup olmadığını denetler.

class C<T>
{
   void F(T x)
   {
      if (x == null)
      {
          throw new ArgumentNullException();
      }
      ...
   }
}

x == null null atanamayan bir değer türünü temsil edebilse de T yapısına izin verilir ve sonuç, false null atanamayan bir değer türü olduğunda T olarak tanımlanır.

son örnek

Formun x == y veya x != ybir işlemi için, geçerli operator == veya operator != varsa, işleç aşırı yükleme çözümlemesi (§12.4.5) kuralları önceden tanımlanmış başvuru türü eşitlik işleci yerine bu işleci seçer.

Not: Her iki işleci de objecttürüne açıkça dönüştürerek önceden tanımlanmış başvuru türü eşitlik operatörünü seçmek her zaman mümkündür. son notu

Örnek: Örnek

class Test
{
    static void Main()
    {
        string s = "Test";
        string t = string.Copy(s);
        Console.WriteLine(s == t);
        Console.WriteLine((object)s == t);
        Console.WriteLine(s == (object)t);
        Console.WriteLine((object)s == (object)t);
    }
}

çıktıyı üretir

True
False
False
False

s ve t değişkenleri aynı karakterleri içeren iki ayrı dize örneğine başvurur. her iki işlenen de türünde Trueolduğunda önceden tanımlanmış dize eşitliği işleci (§12.14.8) seçildiğinden ilk karşılaştırma çıktısı string olur. Geriye kalan tüm karşılaştırmalar, işlenenlerden herhangi birinin bağlama zamanı türü Falseolduğunda operator == türündeki string aşırı yüklemesi geçerli olmadığından, object sonucunu verir.

Yukarıdaki tekniğin değer türleri için anlamlı olmadığını unutmayın. Örnek

class Test
{
    static void Main()
    {
        int i = 123;
        int j = 123;
        Console.WriteLine((object)i == (object)j);
    }
}

çıkış False çünkü dönüşümler, kutulanmış int değerlerinin iki ayrı örneğine başvurular oluşturur.

son örnek

12.14.8 Dize eşitliği işleçleri

Önceden tanımlanmış dize eşitliği işleçleri şunlardır:

bool operator ==(string x, string y);
bool operator !=(string x, string y);

Aşağıdakilerden biri doğru olduğunda iki string değeri eşit kabul edilir:

  • Her iki değerin de nullolduğu görülüyor.
  • Her iki değer, aynı uzunluklara ve her karakter konumunda aynı karakterlere sahip dize örneklerinenull olmayan referanslardır.

Dize eşitliği işleçleri, dize başvuruları yerine dize değerlerini karşılaştırır. İki ayrı dize örneği tam olarak aynı karakter dizisini içerdiğinde, dizelerin değerleri eşittir, ancak başvurular farklıdır.

Not: §12.14.7'de açıklandığı gibi, başvuru türü eşitlik işleçleri dize değerleri yerine dize başvurularını karşılaştırmak için kullanılabilir. son notu

12.14.9 Eşitlik işleçlerini temsilci olarak atama

Önceden tanımlanmış temsilci eşitliği işleçleri şunlardır:

bool operator ==(System.Delegate x, System.Delegate y);
bool operator !=(System.Delegate x, System.Delegate y);

İki temsilci örneği aşağıdaki gibi eşit kabul edilir:

  • Eğer temsilci örneklerinden biri nullise, ancak ve ancak her ikisi de nullise eşit olurlar.
  • Temsilciler farklı çalışma zamanı türlerine sahipse, bunlar hiçbir zaman eşit olmaz.
  • Her iki temsilci örneğinde de çağrı listesi (§21.2) varsa, bu örnekler yalnızca çağrı listeleri aynı uzunluktaysa ve birinin çağırma listesindeki her girdi diğerinin çağrı listesinde sırasıyla ilgili girişe eşitse (aşağıda tanımlandığı gibi) eşittir.

Aşağıdaki kurallar, çağrı listesi girdilerinin eşitliğini yönetir:

  • İki çağrı listesi girdisi de aynı statik yönteme başvuruda bulunursa, girişler eşittir.
  • İki çağrı listesi girdisi de aynı hedef nesnede (başvuru eşitliği işleçleri tarafından tanımlandığı gibi) aynı statik olmayan yönteme başvuruda bulunursa, girişler eşittir.
  • Aynı (büyük olasılıkla boş) yakalanan dış değişken örnekleri kümesine sahip, tek tek özdeş anonim işlevlerin (§12.21) değerlendirilmesinden oluşturulan çağrı listesi girişlerinin eşit olması (ancak gerekli olmaması) gerekir.

İşleç aşırı yükleme çözümlemesi iki temsilci eşitlik işlecine çözümlenirse ve her iki işlenenin de bağlama zamanı türleri yerine §21'deSystem.Delegateaçıklandığı gibi temsilci türleriyse ve bağlama türü işlenen türleri arasında kimlik dönüştürmesi yoksa, bağlama zamanı hatası oluşur.

Not: Bu kural, farklı temsilci türlerinin örneklerine başvuru olması nedeniylenull olmayan değerleri eşit olarak değerlendiremeyen karşılaştırmaları önler. son notu

12.14.10 Null değer türleri ile null değişmez değer arasındaki eşitlik işleçleri

== ve != işleçleri, işlem için önceden tanımlanmış veya kullanıcı tanımlı işleç (kaldırılmamış veya kaldırılmış formda) olmasa bile bir işlenenin null değeri alabilen türde bir değer, diğerinin ise null değişmez değer olmasına izin verir.

Formlardan birinin işlemi için

x == null    null == x    x != null    null != x

burada x, null atanabilir bir değer türünün ifadesidir, işleç aşırı yükleme çözünürlüğü (§12.4.5) uygun bir işleç bulamazsa, sonuç bunun yerine HasValuenesnesinin x özelliğinden hesaplanır. Özellikle, ilk iki form !x.HasValueolarak çevrilir ve son iki form x.HasValueolarak çevrilir.

12.14.11 Tanımlama grubu eşitlik işleçleri

Demet eşitlik operatörleri, demet işleçlerinin öğelerine sözlük sırasına göre çiftler halinde uygulanır.

x veya y işlecinin her bir işleneni == ve !=, ya bir tanımlama grubu ya da tanımlama grubu türünde bir değer olarak sınıflandırılırsa (§8.3.11), bu işleç bir tanımlama grubu eşitliği işlecidir.

İşlenen e bir demet olarak sınıflandırılırsa, e1...en öğeleri, demet ifadesinin öğe ifadelerinin değerlendirilmesi sonuçları olacaktır. Aksi takdirde, e bir demet türünün değeriyse, öğeler, t.Item1...t.Itemn'ün değerlendirilmesinin sonucu t olduğunda e olacaktır.

Bir dizin eşitliği işlecinin x ve y işlenenleri aynı dereceye sahip olmalı, aksi takdirde derleme zamanı hatası oluşur. xi ve yiher öğe çifti için, aynı eşitlik işleci uygulanmalı ve bool, dynamic, bool'e örtük bir dönüşümü olan bir türden, ya da true ve false işleçlerini tanımlayan bir türden olacak şekilde bir sonuç vermelidir.

Tüple eşitlik işleci x == y aşağıdaki şekilde değerlendirilir:

  • Sol taraftaki operand x değerlendirilir.
  • Sağ taraftaki operand y değerlendirilir.
  • Sözcük sırasına göre xi ve yi içeren her bir öğe çifti için:
    • İşleç xi == yi değerlendirilir ve bool türünün sonucu aşağıdaki şekilde elde edilir:
      • Karşılaştırma bir bool verdiyse sonuç bu olur.
      • Aksi takdirde, karşılaştırma bir dynamic verdiyse, false işleci dinamik olarak çağrılır ve sonuçta elde edilen bool değeri mantıksal olumsuzlama işleci (!) ile olumsuzlanır.
      • Aksi takdirde, karşılaştırma türünün bool'a örtük bir dönüşümü varsa, bu dönüşüm uygulanır.
      • Aksi takdirde, karşılaştırmanın türü bir falseişleci içeriyorsa, bu işleç çalıştırılır ve elde edilen bool değeri mantıksal olumsuzlama işleci (!) ile tersine çevrilir.
    • Elde edilen boolfalseise, başka bir değerlendirme gerçekleşmez ve demet eşitlik işlecinin sonucu falseolur.
  • Tüm öğe karşılaştırmaları trueverdiyse, demet eşitlik operatörünün sonucu trueolur.

Tüple eşitlik işleci x != y aşağıdaki şekilde değerlendirilir:

  • Sol taraftaki operand x değerlendirilir.
  • Sağ taraftaki operand y değerlendirilir.
  • Sözcük sırasına göre xi ve yi içeren her bir öğe çifti için:
    • İşleç xi != yi değerlendirilir ve bool türünün sonucu aşağıdaki şekilde elde edilir:
      • Karşılaştırma bir bool verdiyse sonuç bu olur.
      • Aksi takdirde, karşılaştırma bir dynamic verdiyse, true işleci dinamik şekilde çağrılır ve elde edilen bool değer sonuç olarak belirlenir.
      • Aksi takdirde, karşılaştırma türünün bool'a örtük bir dönüşümü varsa, bu dönüşüm uygulanır.
      • Aksi takdirde, karşılaştırma türünün truebir işleci varsa, bu işleç çağrılır ve sonuçta elde edilen bool değeri sonuç olur.
    • Elde edilen booltrueise, başka bir değerlendirme gerçekleşmez ve demet eşitlik işlecinin sonucu trueolur.
  • Tüm öğe karşılaştırmaları falseverdiyse, demet eşitlik operatörünün sonucu falseolur.

12.14.12 is işleci

is işlecinin iki biçimi vardır. Bunlardan biri, sağ tarafta bir türe sahip olan is-türü operatörü'dir. Diğeri ise sağ tarafında bir deseni olan is-pattern operatörü'dür.

12.14.12.1 is-type işleci

türü işleci, bir nesnenin çalışma zamanı türünün belirli bir türle uyumlu olup olmadığını denetlemek için kullanılır. Denetim çalışma zamanında gerçekleştirilir. E is T bir ifade, E ise Tdışında bir tür olan dynamicişleminin sonucu, E'ün null olmayan bir değer olup olmadığını ve başvuru dönüştürmesi, kutulama dönüştürmesi, kutudan çıkarma dönüştürmesi, sarmalama dönüştürmesi veya sarmadan çıkarma dönüştürmesi ile T türüne başarıyla dönüştürülüp dönüştürülemeyeceğini gösteren bir boole değeridir.

İşlem E is T aşağıdaki gibi değerlendirilir:

  1. E anonim bir işlev veya yöntem grubuysa, derleme zamanı hatası oluşur.
  2. Boş değer atanabilir bir başvuru türüyse T (§8.9.3), derleme zamanı hatası oluşur.
  3. Eğer Enull sabit ise veya E'nin değeri nullise, sonuç falseolur.
  4. Yoksa:
    1. R'in çalışma zamanı türü E olsun.
    2. Şu D şekilde türetilebilir R :
      1. R null atanabilir bir değer türüyse, D'nin temel türü R'dir.
      2. Aksi takdirde, DR olur.
    3. Sonuç aşağıdakine bağlıdır DT :
      1. T bir başvuru türüyse, sonuç şu durumda true olur:
        • ve Darasında T bir kimlik dönüştürmesi var veya
        • D bir referans türüdür ve D'den T'ye örtük bir referans dönüştürmesi vardır veya
        • D bir değer türüdür ve bir kutulama dönüştürmesi DT vardır.
      2. Eğer T null atanabilir bir değer türüyse ve true'ün temel alınan türü D ise, sonuç T olur.
      3. Eğer T null atanamaz bir değer türüyse ve true ile D aynı türdeyse, sonuç T olur.
      4. Aksi takdirde sonuç false.

Kullanıcı tanımlı dönüştürmeler is işleci tarafından dikkate alınmaz.

Not: is işleci çalışma zamanında değerlendirildiğinde, tüm tür bağımsız değişkenleri yerine konmuştur ve dikkate alınacak açık türler (§8.4.3) bulunmamaktadır. son notu

Not: is işleci, derleme zamanı türleri ve dönüştürmeleri açısından aşağıdaki gibi anlaşılabilir ve burada CEderleme zamanı türüdür:

  • e derleme zamanı türü Tile aynıysa veya derleme zamanı türünden için örtük bir başvuru dönüştürmesi (§10.2.8), kutulama dönüştürmesi (§10.2.9), sarmalama dönüştürmesi (E) veya açık bir açma dönüştürmesi (T) varsa:
    • C null değer türünde değilse, işlemin sonucu trueolur.
    • Aksi takdirde, işlemin sonucu E != nulldeğerlendirmekle eşdeğerdir.
  • Aksi takdirde, açık bir başvuru dönüştürmesi (§10.3.5) veya kutu açma dönüştürmesi (§10.3.7) öğesinden adresine CTmevcutsa veya açık bir türse CT (§8.4.3) varsa, yukarıdaki çalışma zamanı denetimleri yapılır.
  • Aksi takdirde, E türünden T türüne bağlantı, kutulama, sarmalama veya kutu açma dönüşümü mümkün değildir ve işlemin sonucu falseolur. Derleyici, derleme zamanı türüne göre iyileştirmeler uygulayabilir.

son notu

12.14.12.2 is-pattern işleci

is-pattern işleci, bir ifade tarafından hesaplanan değerin belirli bir desenle (§11) eşleşip eşleşmediğini denetlemek için kullanılır. Denetim çalışma zamanında gerçekleştirilir. Değer desenle eşleşiyorsa is-pattern işlecinin sonucu true olur; aksi takdirde false olur.

E is Pformunun bir ifadesi için, burada ET türünde ilişkisel bir ifadedir ve P bir desendir, aşağıdaki durumların herhangi biri varsa derleme zamanı hatasıdır.

  • E bir değer belirlemez veya türü yoktur.
  • Desen Ptürüne uygulanamaz (T).

Desenin her single_variable_designation, ilgili relational_expression test ettiğinde kesinlikle atanmış yeni bir yerel değişken (true) ekler.

12.14.13 As işleci

as işleci, bir değeri belirli bir referans türüne veya null atanabilir değer türüne açıkça dönüştürmek için kullanılır. Atama ifadelerinden (§12.9.8) farklı olarak as , işleç hiçbir zaman bir özel durum oluşturmaz. Bunun yerine, belirtilen dönüştürme mümkün değilse, sonuçta elde edilen değer nullolur.

E as Tformunda bir işlemde, E bir ifade ve T bir başvuru türü, başvuru türü olduğu bilinen bir tür parametresi veya null değer atayabilir bir değer türü olmalıdır. Ayrıca, aşağıdakilerden en az biri doğru olacaktır veya başka bir şekilde derleme zamanı hatası oluşur:

  • Bir özdeşlik (§10.2.2), örtük null atanabilir (§10.2.6), örtük başvuru (§10.2.8), kutulama (§10.2.9), açık null atanabilir (§10.3.4), açık başvuru (§10.3.5) veya sarmalama (§8.3.12) dönüştürmesi E'den T'e var.
  • E veya T türü açık bir türdür.
  • E, null sabit değerdir.

E derleme zamanı türü dynamicdeğilse, işlem E as T aynı sonucu verir

E is T ? (T)(E) : (T)null

ancak E yalnızca bir kez değerlendirilir. Derleyicinin E as T'ı en fazla bir çalışma zamanı tür denetimi gerçekleştirecek şekilde optimize etmesi beklenebilir; bu, yukarıdaki genişletmede ima edilen iki çalışma zamanı türü denetimine kıyasla daha azdır.

E derleme zamanı türü dynamicise, atama işlecinden farklı olarak as işleci dinamik olarak bağlı değildir (§12.3.3). Bu nedenle bu örnekteki genişletme şu şekildedir:

E is T ? (T)(object)(E) : (T)null

Kullanıcı tanımlı dönüştürmeler gibi bazı dönüştürmelerin as işleciyle mümkün olmadığını ve bunun yerine atama ifadeleri kullanılarak gerçekleştirilmesi gerektiğini unutmayın.

Örnek: Örnekte

class X
{
    public string F(object o)
    {
        return o as string;  // OK, string is a reference type
    }

    public T G<T>(object o)
        where T : Attribute
    {
        return o as T;       // Ok, T has a class constraint
    }

    public U H<U>(object o)
    {
        return o as U;       // Error, U is unconstrained
    }
}

T'in G tür parametresinin, sınıf kısıtlaması olduğu için bir başvuru türü olduğu bilinmektedir. U'nin tür parametresi ne olursa olsun H değildir; bu nedenle as'te H işlecinin kullanımı yasaktır.

son örnek

12.15 Mantıksal işleçler

12.15.1 Genel

&, ^ve | işleçleri mantıksal işleçler olarak adlandırılır.

and_expression
    : equality_expression
    | and_expression '&' equality_expression
    ;

exclusive_or_expression
    : and_expression
    | exclusive_or_expression '^' and_expression
    ;

inclusive_or_expression
    : exclusive_or_expression
    | inclusive_or_expression '|' exclusive_or_expression
    ;

Mantıksal işlecin işleneni dynamicderleme zamanı türüne sahipse, ifade dinamik olarak bağlanır (§12.3.3). Bu durumda ifadenin derleme zamanı türü dynamic'dir ve aşağıda açıklanan çözüm, derleme zamanı türü dynamicolan işlenenlerin çalışma zamanı türü kullanılarak, çalışma zamanında gerçekleşecektir.

x «op» yformunun bir işlemi için , burada «op» mantıksal işleçlerden biridir, belirli bir işleç uygulamasını seçmek için aşırı yükleme çözümlemesi (§12.4.5) uygulanır. Operandlar, seçilen operatörün parametre türlerine dönüştürülür ve sonucun türü operatörün dönüş türüdür.

Önceden tanımlanmış mantıksal işleçler aşağıdaki alt öğelerde açıklanmıştır.

12.15.2 Tamsayı mantıksal işleçleri

Önceden tanımlanmış tamsayı mantıksal işleçleri şunlardır:

int operator &(int x, int y);
uint operator &(uint x, uint y);
long operator &(long x, long y);
ulong operator &(ulong x, ulong y);

int operator |(int x, int y);
uint operator |(uint x, uint y);
long operator |(long x, long y);
ulong operator |(ulong x, ulong y);

int operator ^(int x, int y);
uint operator ^(uint x, uint y);
long operator ^(long x, long y);
ulong operator ^(ulong x, ulong y);

& işleci, iki işlenenin bit düzeyinde mantıksal AND değerini hesaplar, | işleci iki işlenenin bit düzeyinde mantıksal OR değerini hesaplar ve ^ işleci iki işlenenin bit tabanlı mantıksal özel VEYA değerini hesaplar. Bu işlemlerden taşma mümkün değildir.

Yukarıda tanımlanan önceden tanımlanmış kaldırılmamış tamsayı mantıksal işleçlerinin kaldırılmış (§12.4.8) formları da önceden tanımlanmıştır.

12.15.3 Numaralandırma mantıksal işleçleri

Her numaralandırma türü E örtük olarak aşağıdaki önceden tanımlanmış mantıksal işleçleri sağlar:

E operator &(E x, E y);
E operator |(E x, E y);
E operator ^(E x, E y);

x «op» y ve x, temel türü yolan E numaralandırma türü ifadeleri olan ve «op» mantıksal işleçlerden biri olan Udeğerlendirmenin sonucu, (E)((U)x «op» (U)y)değerlendirmekle tam olarak aynıdır. Başka bir deyişle, numaralandırma türü mantıksal işleçleri yalnızca iki işlenenin temel türü üzerinde mantıksal işlemi gerçekleştirir.

Yukarıda tanımlanan kaldırılmamış önceden tanımlanmış sabit listesi mantıksal işleçlerinin genişletilmiş (§12.4.8) formları da önceden tanımlanmıştır.

12.15.4 Boole mantıksal işleçleri

Önceden tanımlanmış Boole mantıksal işleçleri şunlardır:

bool operator &(bool x, bool y);
bool operator |(bool x, bool y);
bool operator ^(bool x, bool y);

** x & y ve truexise, y sonucu true olur. Aksi takdirde sonuç false.

x | y veya true'ten herhangi biri xise, y sonucu true olur. Aksi takdirde sonuç false.

x ^ y true ve xtrueise ya da yfalse ve xfalseise, y sonucu true olur. Aksi takdirde sonuç false. İşlenenler booltüründe olduğunda, ^ işleci != işleciyle aynı sonucu hesaplar.

12.15.5 Boş Değer Atanabilir Boole & ve | Işleç

Değeri null atanabilir Boolean türü bool?, true, falseve nullolmak üzere üç değeri temsil eder.

Diğer ikili işleçlerde olduğu gibi mantıksal işleçlerin & ve | (§12.15.4) kaldırılmış biçimleri de önceden tanımlanmıştır:

bool? operator &(bool? x, bool? y);
bool? operator |(bool? x, bool? y);

Kaldırılan & ve | işleçlerinin semantiği aşağıdaki tablo tarafından tanımlanır:

x y x & y x \| y
true true true true
true false false true
true null null true
false true false true
false false false false
false null false null
null true null true
null false false null
null null null null

Not: bool? türü kavramsal olarak SQL'deki Boole ifadeleri için kullanılan üç değerli türe benzer. Yukarıdaki tablo SQL ile aynı semantiği izler, ancak §12.4.8 kurallarının & ve | işleçlerine uygulanması aynı şekilde olmaz. §12.4.8 kuralları, kaldırılan ^ işleci için SQL benzeri semantikler sağlar. son notu

12.16 Koşullu mantıksal işleçler

12.16.1 Genel

&& ve || işleçleri koşullu mantıksal işleçler olarak adlandırılır. Bunlara "kısa devre" mantıksal işleçleri de denir.

conditional_and_expression
    : inclusive_or_expression
    | conditional_and_expression '&&' inclusive_or_expression
    ;

conditional_or_expression
    : conditional_and_expression
    | conditional_or_expression '||' conditional_and_expression
    ;

&& ve || işleçleri, & ve | işleçlerinin koşullu sürümleridir:

  • İşlem x && yx & yişlemine karşılık gelir, ancak y yalnızca xfalsedeğilse değerlendirilir.
  • İşlem x || yx | yişlemine karşılık gelir, ancak y yalnızca xtruedeğilse değerlendirilir.

Not: Kısa devrenin 'doğru değil' ve 'yanlış değil' koşullarını kullanmasının nedeni, kullanıcı tanımlı koşullu işleçlerin kısa devrenin ne zaman uygulandığını tanımlamasını sağlamaktır. Kullanıcı tanımlı türler, operator true'ın false ve operator false'nin falsedöndürdüğü bir durumda olabilir. Bu gibi durumlarda, ne && ne de || kısa devre yapar. son notu

Koşullu mantıksal işlecin işlenenin derleme zamanı türü dynamicise, ifade dinamik olarak bağlıdır (§12.3.3). Bu durumda ifadenin derleme zamanı türü dynamic'dir ve aşağıda açıklanan çözüm, derleme zamanı türü dynamicolan işlenenlerin çalışma zamanı türü kullanılarak, çalışma zamanında gerçekleşecektir.

Bir x && y veya x || y şeklindeki işlem, sanki işlem veya x & yolarak yazılmış gibi aşırı yük çözümlemesi (x | y) uygulanarak işlenir. Sonra

  • Aşırı yükleme çözümlemesi tek bir en iyi işleci bulamazsa veya aşırı yükleme çözümlemesi önceden tanımlanmış tamsayı mantıksal işleçlerinden birini veya boş değer atanabilir Boole mantıksal işleçlerinden birini seçerse (§12.15.5), bağlama zamanı hatası oluşur.
  • Aksi takdirde, seçilen işleç önceden tanımlanmış Boole mantıksal işleçlerinden biriyse (§12.15.4), işlem §12.16.2'de açıklandığı gibi işlenir.
  • Aksi takdirde, seçilen işleç kullanıcı tanımlı bir işleçtir ve işlem §12.16.3'te açıklandığı gibi işlenir.

Koşullu mantıksal işleçleri doğrudan aşırı yüklemek mümkün değildir. Ancak, koşullu mantıksal işleçler normal mantıksal işleçler açısından değerlendirildiğinden, normal mantıksal işleçlerin aşırı yüklemeleri, belirli kısıtlamalarla birlikte koşullu mantıksal işleçlerin aşırı yüklemeleri olarak da kabul edilir. Bu, §12.16.3'te daha ayrıntılı olarak açıklanmıştır.

12.16.2 Boole koşullu mantıksal işleçleri

&& veya || işlenenleri booltüründeyse veya işlenenler geçerli bir operator & veya operator |tanımlamayan, ancak bool'e örtük dönüştürmeleri tanımlayan türlerden olduğunda, işlem aşağıdaki şekilde gerçekleştirilir:

  • İşlem x && yx ? y : falseolarak değerlendirilir. Başka bir deyişle, x önce değerlendirilir ve booltürüne dönüştürülür. Ardından, xtrueise, y değerlendirilir ve booltürüne dönüştürülür ve bu işlemin sonucu olur. Aksi halde, işlemin sonucu falseolur.
  • İşlem x || yx ? true : yolarak değerlendirilir. Başka bir deyişle, x önce değerlendirilir ve booltürüne dönüştürülür. Ardından, xtrueise işlemin sonucu trueolur. Aksi takdirde, y değerlendirilir ve booltürüne dönüştürülür ve bu işlemin sonucu olur.

12.16.3 Kullanıcı tanımlı koşullu mantıksal işleçler

&& veya || işlenenleri, geçerli bir kullanıcı tanımlı operator & veya operator |bildiren türlerden olduğunda, aşağıdakilerin her ikisi de doğru olmalıdır. Burada T, seçilen işlecin bildirildiği tür olmaktadır:

  • Dönüş türü ve seçilen işlecin her parametresinin türü Tolacaktır. Başka bir deyişle işleç, Ttüründeki iki işlenenin mantıksal AND veya mantıksal OR değerlerini hesaplar ve Ttüründen bir sonuç döndürür.
  • T, operator true bildirimlerini ve operator falsebildirimlerini içermelidir.

Bu gereksinimlerden biri karşılanmazsa bağlama zamanı hatası oluşur. Aksi takdirde, && veya || işlemi, kullanıcı tanımlı operator true veya operator false seçilen kullanıcı tanımlı işleçle birleştirilerek değerlendirilir:

  • İşlem x && y, T.false(x) ? x : T.&(x, y)olarak değerlendirilir; burada T.false(x), operator falseiçinde bildirilen T'ün bir çağrısıdır ve T.&(x, y), seçili operator &'nın bir çağrısıdır. Başka bir deyişle, x önce değerlendirilir ve operator false kesinlikle yanlış olup olmadığını belirlemek için sonuç üzerinde x çağrılır. Ardından, x kesinlikle false ise, işlemin sonucu daha önce xiçin hesaplanan değerdir. Aksi takdirde, y değerlendirilir ve seçilen operator & daha önce x için hesaplanan değerde ve işlemin sonucunu üretmek üzere y için hesaplanan değerde çağrılır.
  • İşlem x || y, T.true(x) ? x : T.|(x, y)olarak değerlendirilir; burada T.true(x), operator trueiçinde bildirilen T'ün bir çağrısıdır ve T.|(x, y), seçili operator |'nın bir çağrısıdır. Başka bir deyişle, x önce değerlendirilir ve operator true kesinlikle doğru olup olmadığını belirlemek için sonuç üzerinde x çağrılır. Ardından, x kesinlikle doğruysa, işlemin sonucu daha önce xiçin hesaplanan değerdir. Aksi takdirde, y değerlendirilir ve seçilen operator | daha önce x için hesaplanan değerde ve işlemin sonucunu üretmek üzere y için hesaplanan değerde çağrılır.

Bu işlemlerden herhangi birinde, x tarafından verilen ifade yalnızca bir kez değerlendirilir ve y tarafından verilen ifade ya değerlendirilmez ya da tam olarak bir kez değerlendirilir.

12.17 Null birleşim işleci

?? işleci null birleşim işleci olarak adlandırılır.

null_coalescing_expression
    : conditional_or_expression
    | conditional_or_expression '??' null_coalescing_expression
    | throw_expression
    ;

Şu şekliyle bir null birleşim ifadesinde a ?? b, eğer anulldeğilse, sonuç a; diğer durumlarda, sonuç b. İşlem, yalnızca baolduğunda null'ı değerlendirir.

Null birleşim işleci sağ ilişkilendiricidir, yani işlemler sağdan sola gruplandırılır.

Örnek: Form a ?? b ?? c ifadesi a ?? (b ?? c)olarak değerlendirilir. Genel olarak, E1 ?? E2 ?? ... ?? EN şeklindeki bir ifade,nullolmayan işleçlerin ilkini veya tüm işleçler nullise null döndürür. son örnek

a ?? b ifadenin türü, operatörlerde hangi örtük dönüştürmelerin kullanılabilir olduğuna bağlıdır. Tercih sırasına göre, a ?? b türü A₀, Aveya B'tür; burada, A, a türüdür (eğer a'nın türü varsa), B, btürüdür (eğer b'un türü varsa) ve A₀, A bir null değer türüyse, temel türü A'dir; aksi takdirde A'tür. Özellikle, a ?? b aşağıdaki gibi işlenir:

  • A Varsa ve yönetilmeyen bir türse (§8.8) veya null olmayan bir değer türü olarak biliniyorsa, derleme zamanı hatası oluşur.
  • Aksi takdirde, A varsa ve b dinamik bir ifadeyse, sonuç türü dynamicolur. Çalışma zamanında ilk olarak a değerlendirilir. a nulldeğilse, adynamicdönüştürülür ve sonuç olur. Aksi takdirde, b değerlendirilir ve sonuç olarak kabul edilir.
  • Aksi takdirde, A varsa ve null atanabilir bir değer türüyse ve b'den A₀'a örtük bir dönüştürme varsa, sonuç türü A₀olur. Çalışma zamanında ilk olarak a değerlendirilir. a nulldeğilse, aA₀türüne göre açık hale getirilir ve sonuç bu olur. Aksi takdirde, b değerlendirilir ve A₀türüne dönüştürülür ve sonuç haline gelir.
  • Aksi takdirde, A varsa ve b'dan A'a örtük bir dönüştürme varsa, sonuç türü Aolur. Çalışma zamanında ilk olarak a değerlendirilir. a nulldeğilse, sonuç a olur. Aksi takdirde, b değerlendirilir ve Atürüne dönüştürülür ve sonuç haline gelir.
  • Aksi takdirde, A varsa ve null atanabilir bir değer türündeyse, b türü B olduğunda ve A₀'ten B'e örtük bir dönüşüm varsa, sonuç türü B'tir. Çalışma zamanında ilk olarak a değerlendirilir. a nulldeğilse, aA₀ türüne açılır ve Btürüne dönüştürülür, sonuç bu olur. Aksi takdirde, b değerlendirilir ve sonuç olarak kabul edilir.
  • Aksi takdirde, b bir tür B varsa ve a'den B'e örtük bir dönüştürme varsa, sonuç türü Bolur. Çalışma zamanında ilk olarak a değerlendirilir. a nulldeğilse, aBtürüne dönüştürülür ve sonuç olur. Aksi takdirde, b değerlendirilir ve sonuç olarak kabul edilir.
  • Aksi takdirde, a ve b uyumsuz olur ve derleme zamanı hatası oluşur.

Örnek:

T M<T>(T a, T b) => a ?? b;

string s = M(null, "text");
int i = M(19, 23);

Yöntemin T tür parametresi M kısıtlanmamış. Bu nedenle tür bağımsız değişkeni, ilk çağrısında M gösterildiği gibi bir referans türü veya null atanabilir değer türü olabilir. tür bağımsız değişkeni, ikinci çağrısında Mgösterildiği gibi null atanamaz bir değer türü de olabilir. Tür bağımsız değişkeni null atanamaz bir değer türü olduğunda, ifadenin a ?? b değeri şeklindedir a.

son örnek

12.18 Throw ifadesi işleci

throw_expression
    : 'throw' null_coalescing_expression
    ;

throw_expression, null_coalescing_expressiondeğerlendirildiğinde üretilen değeri atar. İfade örtük şekilde System.Exception'ye dönüştürülebilir ve ifadenin değerlendirilmesinin sonucu, önce System.Exception'e dönüştürülüp sonra atılır. throw ifadesinin değerlendirilmesinin çalışma zamanındaki davranışı, throw deyimi (§13.10.6) için belirtilen davranışla aynıdır.

throw_expression türü yoktur. throw_expression, örtük throw dönüştürmetarafından her türe dönüştürülebilir.

throw ifadesi yalnızca aşağıdaki söz dizimsel bağlamlarda gerçekleşecektir:

  • Üçüncül koşullu işlecin ikinci veya üçüncü operandı olarak (?:).
  • Null birleşim işlecinin ikinci işleneni olarak (??).
  • İfade gövdesi olan lambda veya üyenin gövdesi olarak.

12.19 Bildirim ifadeleri

Bildirim ifadesi yerel bir değişken bildirir.

declaration_expression
    : local_variable_type identifier
    ;

local_variable_type
    : type
    | 'var'
    ;

Basit ad arama ilişkili bir bildirim bulamadıysa simple_name_ de bildirim ifadesi olarak kabul edilir (§12.8.4). Bildirim ifadesi olarak kullanıldığında, _basit atma olarak adlandırılır. var _ile eşdeğerdir, ancak daha fazla yerde izin verilir.

Bildirim ifadesi yalnızca aşağıdaki söz dizimsel bağlamlarda gerçekleşecektir:

  • Bir outargument_value, bir argument_listolarak.
  • Basit bir atamanın sol tarafını oluşturan basit bir atma _ olarak (§12.23.2).
  • Bir veya daha fazla özyinelemeli iç içe yerleştirilmiş tuple_expressioniçinde bir tuple_element olarak, en dışta olanı, bir yapısızlaştırma atamasının sol tarafını oluşturur. deconstruction_expression, bildirim ifadeleri söz dizimsel olarak mevcut olmasa bile bu konumda bildirim ifadelerinin ortaya çıkmasına neden olur.

Not: Bu, bildirim ifadesinin parantez içinde alınamayacağı anlamına gelir. son notu

Bu bir hatadır: Bir declaration_expression ile bildirilen örtük yazımlı bir değişkene, bildirildiği yer olan argument_list içinde başvurmak.

Bir declaration_expression ile bildirilen bir değişkene, tanımlandığı yıkıcı atama içinde başvurmak hatadır.

Basit bir atma olan veya local_variable_type tanımlayıcı olduğu var bildirim ifadesi, örtük olarak yazılan değişkeni olarak sınıflandırılır. İfadenin türü yoktur ve yerel değişkenin türü, söz diziminin bağlamı temelinde aşağıdaki gibi çıkarılır:

  • bir argument_list değişkeninin çıkarım türü, karşılık gelen parametrenin bildirilen türüdür.
  • Basit bir atamanın sol tarafı olarak, değişkenin çıkarsanan türü atamanın sağ tarafının türüdür.
  • Basit bir atamanın sol tarafındaki tuple_expression, değişkenin çıkarılan türü, atamanın sağ tarafındaki karşılık gelen demet öğesinin türüdür (yapısızlaştırmadan sonra).

Aksi takdirde, bildirim ifadesi açıkça yazılan değişkeni olarak sınıflandırılır ve ifadenin türü ve bildirilen değişkenin türü local_variable_typetarafından verilmiş olmalıdır.

_ tanımlayıcısına sahip bir bildirim ifadesi bir atmadır (§9.2.9.2) ve değişken için bir ad oluşturmaz. _ dışında bir tanımlayıcıya sahip bir bildirim ifadesi, bu adı en yakın kapsayan yerel değişken bildirim alanına tanıtır (§7.3).

Örnek:

string M(out int i, string s, out bool b) { ... }

var s1 = M(out int i1, "One", out var b1);
Console.WriteLine($"{i1}, {b1}, {s1}");
// Error: i2 referenced within declaring argument list
var s2 = M(out var i2, M(out i2, "Two", out bool b2), out b2);
var s3 = M(out int _, "Three", out var _);

s1 bildirimi hem açıkça hem de örtük olarak yazılan bildirim ifadelerini gösterir. b1 çıkarım türü bool çünkü bu, M1içindeki ilgili çıkış parametresinin türüdür. Sonraki WriteLine, çevreleyen kapsama eklenen i1 ve b1'ye erişebilir.

s2 bildirimi, i2'ün bildirildiği bağımsız değişken listesinde yer aldığı için, M'nin iç içe çağrısında i2'i kullanma girişiminin yasak olduğunu gösterir. Öte yandan son argümanda b2 referansına izin verilir, çünkü iç içe argüman listesinin sonunda b2'in bildirildiği yerden sonra gerçekleşir.

s3 bildirimi, hem örtük hem de açıkça yazılan ve atılan bildirim ifadelerinin kullanıldığını gösterir. Atıklar adlandırılmış bir değişken bildirmediğinden, tanımlayıcı _'ın birden çok kez kullanılmasına izin verilir.

(int i1, int _, (var i2, var _), _) = (1, 2, (3, 4), 5);

Bu örnek, değişkenler ve önemsemeyen değerler için örtük ve açıkça yazılmış bildirim ifadelerinin bir yapı çözme atamasında kullanılmasını gösterir. simple_name_, var _ bildirimi bulunamadığında _ eşdeğerdir.

void M1(out int i) { ... }

void M2(string _)
{
    M1(out _);      // Error: `_` is a string
    M1(out var _);
}

Bu örnek, var _ kullanılamadığında örtük türde bir atma sağlamak için _ kullanımını gösterir, çünkü kapsayıcı kapsamda bir değişken belirtir.

son örnek

12.20 Koşullu işleç

?: işleci koşullu işleç olarak adlandırılır. Bazen üçüncül işleç olarak da adlandırılır.

conditional_expression
    : null_coalescing_expression
    | null_coalescing_expression '?' expression ':' expression
    | null_coalescing_expression '?' 'ref' variable_reference ':'
      'ref' variable_reference
    ;

Varsa koşullu işleçte throw ifadelerine (ref) izin verilmez.

Formun koşullu ifadesi b ? x : y önce bkoşulunu değerlendirir. Ardından, btrueise x değerlendirilir ve işlemin sonucu olur. Aksi takdirde, y değerlendirilir ve işlemin sonucu haline gelir. Koşullu ifade hiçbir zaman hem x hem de ydeğerlendirmez.

Koşullu işleç sağ ilişkilendiricidir, yani işlemler sağdan sola gruplandırılır.

Örnek: Form a ? b : c ? d : e ifadesi a ? b : (c ? d : e)olarak değerlendirilir. son örnek

?: işlecinin ilk işleneni, bool'e dönüştürülebilen bir ifade veya operator true'ü uygulayan bir türün ifadesi olmalıdır. Bu gereksinimlerin hiçbiri karşılanmadıysa derleme zamanı hatası oluşur.

ref mevcutsa:

  • İki variable_referencetürü arasında bir kimlik dönüştürmesi bulunmalıdır ve sonucun türü her iki türde de olabilir. Türlerden biri dynamicise tür çıkarımı dynamic tercih eder (§8,7). Türlerden biri bir tanımlama grubu türüyse (§8.3.11), tür çıkarımı, aynı sıradaki öğe adlarının her iki tanımlama grubunda da eşleştiği durumda bu adları içerir.
  • Sonuç, her iki değişken referansıde yazılabilirse yazılabilir bir değişken referansıdır.

Not: ref olduğunda, conditional_expression bir değişken referansı döndürür, bu referans = ref işleci kullanılarak bir referans değişkenine atanabilir veya referans/girdi/çıktı parametresi olarak geçirilebilir. son notu

ref eksikse, x işlecinin ikinci ve üçüncü işlenenleri, y ve ?:, koşullu ifadenin türünü denetler.

  • x türü X ve y türü Y ise,
    • ile arasında X bir kimlik dönüştürmesi varsa, sonuç bir ifade kümesinin en iyi ortak türüdür (Y). Türlerden biri dynamicise tür çıkarımı dynamic tercih eder (§8,7). Türlerden biri bir tanımlama grubu türüyse (§8.3.11), tür çıkarımı, aynı sıradaki öğe adlarının her iki tanımlama grubunda da eşleştiği durumda bu adları içerir.
    • Aksi takdirde, 'den X'a örtük dönüştürme (Y) varsa, ancak Y'dan X'a kadar değilse, koşullu ifadenin türü Y olur.
    • Aksi takdirde, 'dan X'a örtük bir numaralandırma dönüştürmesi (Y) varsa, koşullu ifadenin türü Y olur.
    • Aksi takdirde, 'dan Y'a örtük bir numaralandırma dönüştürmesi (X) varsa, koşullu ifadenin türü X olur.
    • Aksi takdirde, 'den Y'a örtük dönüştürme (X) varsa, ancak X'dan Y'a kadar değilse, koşullu ifadenin türü X olur.
    • Aksi takdirde, hiçbir ifade türü belirlenemez ve derleme zamanı hatası oluşur.
  • x ve y yalnızca birinin türü varsa ve hem x hem de y bu türe örtük olarak dönüştürülebilirse, bu koşullu ifadenin türüdür.
  • Aksi takdirde, hiçbir ifade türü belirlenemez ve derleme zamanı hatası oluşur.

b ? ref x : ref y biçimindeki başvuru koşullu ifadesinin çalışma zamanında işlenmesi, aşağıdaki adımlardan oluşur.

  • İlk olarak, b değerlendirilir ve bool'nin b değeri belirlenir:
    • b türünden bool'e örtük bir dönüştürme varsa, bu örtük dönüştürme bool bir değer üretmek için gerçekleştirilir.
    • Aksi takdirde, operator true türü tarafından tanımlanan b, bir bool değeri üretmek için çağrılır.
  • Yukarıdaki adım tarafından üretilen bool değeri trueise x değerlendirilir ve sonuçta elde edilen değişken başvurusu koşullu ifadenin sonucu olur.
  • Aksi takdirde, y değerlendirilir ve sonuçta elde edilen değişken başvurusu koşullu ifadenin sonucu olur.

Form b ? x : y koşullu ifadesinin çalışma zamanı işlemesi aşağıdaki adımlardan oluşur:

  • İlk olarak, b değerlendirilir ve bool'nin b değeri belirlenir:
    • b türünden bool'e örtük bir dönüştürme varsa, bu örtük dönüştürme bool bir değer üretmek için gerçekleştirilir.
    • Aksi takdirde, operator true türü tarafından tanımlanan b, bir bool değeri üretmek için çağrılır.
  • Yukarıdaki adım tarafından üretilen bool değeri trueise, x değerlendirilir ve koşullu ifadenin türüne dönüştürülür ve bu koşullu ifadenin sonucu olur.
  • Aksi takdirde, y değerlendirilir ve koşullu ifadenin türüne dönüştürülür ve bu koşullu ifadenin sonucu olur.

12.21 Anonim işlev ifadeleri

12.21.1 Genel

anonim işlev, "satır içi" yöntem tanımını temsil eden bir ifadedir. Anonim bir işlevin kendi içinde bir değeri veya türü yoktur, ancak uyumlu bir temsilciye veya ifade ağacı türüne dönüştürülebilir. Anonim işlev dönüştürmesinin değerlendirilmesi, dönüştürmenin hedef türüne bağlıdır: Bu bir temsilci türüyse, dönüştürme anonim işlevin tanımladığı yönteme başvuran bir temsilci değeri olarak değerlendirilir. Bu bir ifade ağacı türüyse, dönüştürme yöntemin yapısını nesne yapısı olarak temsil eden bir ifade ağacı olarak değerlendirilir.

Not: Tarihsel nedenlerden dolayı, anonim fonksiyonların iki sözdizimsel çeşidi vardır; bunlar, lambda_expression'ler ve anonymous_method_expression'lerdir. Neredeyse tüm amaçlar için lambda_expression, geriye dönük uyumluluk için dilde kalan anonymous_method_expression'lerden daha kısa ve açıklayıcıdır. son notu

lambda_expression
    : 'async'? anonymous_function_signature '=>' anonymous_function_body
    ;

anonymous_method_expression
    : 'async'? 'delegate' explicit_anonymous_function_signature? block
    ;

anonymous_function_signature
    : explicit_anonymous_function_signature
    | implicit_anonymous_function_signature
    ;

explicit_anonymous_function_signature
    : '(' explicit_anonymous_function_parameter_list? ')'
    ;

explicit_anonymous_function_parameter_list
    : explicit_anonymous_function_parameter
      (',' explicit_anonymous_function_parameter)*
    ;

explicit_anonymous_function_parameter
    : anonymous_function_parameter_modifier? type identifier
    ;

anonymous_function_parameter_modifier
    : 'ref'
    | 'out'
    | 'in'
    ;

implicit_anonymous_function_signature
    : '(' implicit_anonymous_function_parameter_list? ')'
    | implicit_anonymous_function_parameter
    ;

implicit_anonymous_function_parameter_list
    : implicit_anonymous_function_parameter
      (',' implicit_anonymous_function_parameter)*
    ;

implicit_anonymous_function_parameter
    : identifier
    ;

anonymous_function_body
    : null_conditional_invocation_expression
    | expression
    | 'ref' variable_reference
    | block
    ;

Bir anonymous_function_body tanındığında, hem null_conditional_invocation_expression hem de ifade alternatiflerinin her ikisi de geçerliyse, önceki seçilmelidir.

Not: Buradaki alternatiflerin çakışması ve önceliği yalnızca açıklayıcı kolaylık sağlamak içindir; dil bilgisi kuralları, çakışmayı kaldırmak için ayrıntılı bir şekilde anlatılabilir. ANTLR ve diğer dil bilgisi sistemleri aynı kolaylıkları benimseyerek anonymous_function_body belirtilen semantiği otomatik olarak kullanır. son notu

Not: Bir ifade olarak ele alındığında, 'nin sonuç türü x?.M() ise, M gibi söz dizimli bir form hata olursa (void). Ancak bir null_conditional_invocation_expressionolarak kabul edildiğinde, sonuç türüne voidizin verilebilir. son notu

Örnek: List<T>.Reverse'nin sonuç türü void'tür. Aşağıdaki kodda anonim ifadenin gövdesi bir null_conditional_invocation_expressionolduğu için bu bir hata değildir.

Action<List<int>> a = x => x?.Reverse();

son örnek

=> işleci atama (=) ile aynı önceliğe sahiptir ve doğru ilişkilendirilmiştir.

Değiştirici ile async anonim bir işlev zaman uyumsuz bir işlevdir ve §15.14'te açıklanan kurallara uyar.

Anonim bir işlevin lambda_expression biçimindeki parametreleri açıkça veya örtük olarak yazılabilir. Açıkça yazılan bir parametre listesinde, her parametrenin türü açıkça belirtilir. Örtük olarak yazılan parametre listesinde, parametre türleri anonim işlevin gerçekleştiği bağlamdan çıkarılır; özellikle anonim işlev uyumlu bir temsilci türüne veya ifade ağacı türüne dönüştürüldüğünde, bu tür parametre türlerini sağlar (§10.7).

Örtük olarak belirtilmiş tek bir parametreye sahip lambda_expression olan bir ifadede, parametre listesinden parantezler atlanabilir. Başka bir deyişle, formun anonim bir işlevi

( «param» ) => «expr»

şu şekilde kısaltılabilir

«param» => «expr»

anonymous_method_expression biçiminde anonim bir işlevin parametre listesi isteğe bağlıdır. Verilirse, parametreler açıkça yazılmalıdır. Aksi takdirde, anonim işlev, çıkış parametreleri içermeyen herhangi bir parametre listesine sahip bir temsilciye dönüştürülebilir.

Anonim bir işlevin blok gövdesine her zaman ulaşılabilir (§13.2).

Örnek: Anonim işlevlerin bazı örnekleri aşağıda verilmiştir:

x => x + 1                             // Implicitly typed, expression body
x => { return x + 1; }                 // Implicitly typed, block body
(int x) => x + 1                       // Explicitly typed, expression body
(int x) => { return x + 1; }           // Explicitly typed, block body
(x, y) => x * y                        // Multiple parameters
() => Console.WriteLine()              // No parameters
async (t1,t2) => await t1 + await t2   // Async
delegate (int x) { return x + 1; }     // Anonymous method expression
delegate { return 1 + 1; }             // Parameter list omitted

son örnek

lambda_expressionve anonymous_method_expressiondavranışları aşağıdaki noktalar dışında aynıdır:

  • anonymous_method_expression, parametre listesinin tamamen atlanmasına izin verir ve herhangi bir değer parametresi listesinin temsilci türlerine dönüştürülebilirlik sağlar.
  • lambda_expressionparametre türlerinin atlanıp çıkarılmalarına izin verirken, anonymous_method_expressionparametre türlerinin açıkça belirtilmesi gerekir.
  • bir lambda_expression gövdesi bir ifade veya blok olabilirken, bir anonymous_method_expression gövdesi bir blok olmalıdır.
  • Sadece lambda_expressionuyumlu ifade ağacı türlerine (§8.6) dönüştürülebilir.

12.21.2 Anonim işlev imzaları

Anonim bir işlevin anonymous_function_signature adları ve isteğe bağlı olarak anonim işlev için parametre türlerini tanımlar. Anonim işlevin parametrelerinin kapsamı anonim_işlev_gövdesi (§7.7). Parametre listesiyle birlikte (verilirse) anonim-method-body bir bildirim alanı oluşturur (§7.3). Bu nedenle, anonim işlevin parametresinin adının, kapsamı anonymous_method_expression veya lambda_expressioniçeren bir yerel değişken, yerel sabit veya parametreyle aynı olması’nın bir derleme zamanı hatası oluşturacağı unutulmamalıdır.

Eğer anonim bir işlev bir explicit_anonymous_function_signatureiçeriyorsa, uyumlu temsilci türleri ve ifade ağacı türleri yalnızca aynı parametre türlerine ve değiştiricilere aynı sırayla sahip olanlarla sınırlıdır (§10.7). Yöntem grubu dönüştürmelerinin aksine (§10.8), anonim işlev parametre türlerinin ters varyansı desteklenmez. Anonim bir işlevin anonymous_function_signatureyoksa, uyumlu temsilci türleri ve ifade ağacı türleri kümesi, çıkış parametresi bulunmayanlarla sınırlıdır.

bir anonymous_function_signature öznitelikleri veya parametre dizilerini içeremeyeceğini unutmayın. Bununla birlikte, bir anonymous_function_signature parametre listesi parametre dizisi içeren bir temsilci türüyle uyumlu olabilir.

Ayrıca, uyumlu olsa bile ifade ağacı türüne dönüştürmenin derleme zamanında (§8.6) başarısız olabileceğini unutmayın.

12.21.3 Anonim işlev gövdeleri

Anonim bir işlevin gövdesi (ifade veya bloğu) aşağıdaki kurallara tabidir:

  • Anonim işlev bir imza içeriyorsa, imzada belirtilen parametreler gövdede kullanılabilir. Anonim işlevin imzası yoksa, parametreleri (§10.7) olan bir temsilci türüne veya ifade türüne dönüştürülebilir, ancak parametrelere gövdede erişilemez.
  • Referansla belirtilmiş parametreler dışında, en yakın kapsayan anonim işlevin imzasında (varsa) belirtilen, gövdenin bir referans parametresine erişmesi derleme zamanı hatasıdır.
  • İmzasında (varsa) belirtilen parametreler dışında, en yakın anonim işlevin gövdesinin ref struct türünde bir parametreye erişmesi, derleme zamanı hatasına neden olur.
  • this türü bir yapı türü olduğunda, gövde this'e erişirse derleme hatası oluşur. Erişimin açık (this.xolduğu gibi) veya örtük (x'nin yapının örnek üyesi olduğu x olduğu gibi) olması durumu değiştirmez. Bu kural yalnızca bu tür bir erişimi yasaklar ve üye aramasının yapının bir üyesiyle sonuçlanıp sonuçlanmadığını etkilemez.
  • Gövde, anonim işlevin dış değişkenlerine (§12.21.6) erişebilir. Dış değişkenin erişimi, lambda_expression veyaanonymous_method_expression değerlendirildiğinde etkin olan değişkenin örneğine başvurur (§12.21.7).
  • Gövde, hedefi gövdenin dışarısında ya da anonim bir işlevin içerisinde olan bir goto deyimi, bir break deyimi veya bir continue deyimi içeriyorsa, bu derleme zamanı hatasıdır.
  • Gövdedeki return deyimi, kapsayan işlev üyesinden değil, en yakın kapsayan anonim işlevin çağrısından denetimi döndürür.

Anonim bir işlevin bloğunu yürütmenin, lambda_expression veya anonymous_method_expressiondeğerlendirilmesi ve çağrılması dışında bir yolu olup olmadığı açıkça belirtilmemiştir. Özellikle, bir derleyici bir veya daha fazla adlandırılmış yöntem veya türü sentezleyerek anonim bir işlev uygulamayı seçebilir. Bu tür sentezlenen öğelerin adları derleyici kullanımı için ayrılmış bir biçimde olmalıdır (§6.4.3).

12.21.4 Aşırı yükleme çözünürlüğü

Bağımsız değişken listesindeki anonim işlevler tür çıkarımına ve aşırı yükleme çözümlemeye katılır. Tam kurallar için §12.6.3 ve §12.6.4 bakın.

Örnek: Aşağıdaki örnekte anonim işlevlerin aşırı yükleme çözümlemesi üzerindeki etkisi gösterilmektedir.

class ItemList<T> : List<T>
{
    public int Sum(Func<T, int> selector)
    {
        int sum = 0;
        foreach (T item in this)
        {
            sum += selector(item);
        }
        return sum;
    }

    public double Sum(Func<T, double> selector)
    {
        double sum = 0;
        foreach (T item in this)
        {
            sum += selector(item);
        }
        return sum;
    }
}

ItemList<T> sınıfının iki Sum yöntemi vardır. Her biri bir selector bağımsız değişkeni alır ve bu bağımsız değişken, bir liste öğesinden toplanacak değeri ayıklar. Ayıklanan değer bir int veya double olabilir ve sonuçta elde edilen toplam aynı şekilde bir int veya doubleolur.

örneğin Sum yöntemleri, bir sıralı ayrıntı satırları listesinden toplamları hesaplamak için kullanılabilir.

class Detail
{
    public int UnitCount;
    public double UnitPrice;
    ...
}

class A
{
    void ComputeSums()
    {
        ItemList<Detail> orderDetails = GetOrderDetails( ... );
        int totalUnits = orderDetails.Sum(d => d.UnitCount);
        double orderTotal = orderDetails.Sum(d => d.UnitPrice * d.UnitCount);
        ...
    }

    ItemList<Detail> GetOrderDetails( ... )
    {
        ...
    }
}

orderDetails.Sumilk çağrıda, anonim işlev Sum hem d => d.UnitCount hem de Func<Detail,int>ile uyumlu olduğundan her iki Func<Detail,double> yöntemi de uygulanabilir. Ancak, Sum dönüştürme Func<Detail,int>dönüştürmeden daha iyi olduğundan, aşırı yükleme çözümlemesi ilk Func<Detail,double> yöntemini seçer.

orderDetails.Sumikinci çağrıda, anonim işlev Sumd => d.UnitPrice * d.UnitCounttüründe bir değer ürettiğinden yalnızca ikinci double yöntemi uygulanabilir. Bu nedenle, aşırı yükleme çözümlemesi bu çağrı için ikinci Sum yöntemini seçer.

son örnek

12.21.5 Anonim işlevler ve dinamik bağlama

Anonim işlev, dinamik olarak bağlı bir işlemin alıcısı, bağımsız değişkeni veya işleneni olamaz.

12.21.6 Dış değişkenler

12.21.6.1 Genel

Kapsamı lambda_expression veya anonymous_method_expression içeren herhangi bir yerel değişken, değer parametresi veya parametre dizisi anonim işlevin dış değişkeni olarak adlandırılır. Bir sınıfın örnek işlev üyesinde, bu değer bir değer parametresi olarak kabul edilir ve işlev üyesi içinde yer alan herhangi bir anonim işlevin dış değişkenidir.

12.21.6.2 Yakalanan dış değişkenler

Bir dış değişkene anonim bir işlev tarafından başvurulduğunda, dış değişkenin anonim işlev tarafından yakalandığı söylenir. Normalde, yerel değişkenin ömrü ilişkili olduğu bloğun veya deyimin yürütülmesiyle sınırlıdır (§9.2.9.1). Ancak, yakalanan bir dış değişkenin ömrü en azından anonim işlevden oluşturulan temsilci veya ifade ağacı çöp toplama için uygun hale gelene kadar uzatılır.

Örnek: Örnekte

delegate int D();

class Test
{
    static D F()
    {
        int x = 0;
        D result = () => ++x;
        return result;
    }

    static void Main()
    {
        D d = F();
        Console.WriteLine(d());
        Console.WriteLine(d());
        Console.WriteLine(d());
    }
}

yerel değişken x anonim işlev tarafından yakalanır ve x ömrü en azından F döndürülen temsilci çöp toplama için uygun hale gelene kadar uzatılır. Anonim işlevin her çağrısı aynı xörneğinde çalıştığından, örneğin çıktısı şöyledir:

1
2
3

son örnek

Bir yerel değişken veya değer parametresi anonim bir işlev tarafından yakalandığında, yerel değişken veya parametre artık sabit değişken (§24.4) olarak kabul edilmez, ancak bunun yerine taşınabilir değişken olarak kabul edilir. Ancak, yakalanan dış değişkenler deyiminde fixed (§24.7) kullanılamaz, bu nedenle yakalanan dış değişkenin adresi alınamaz.

Not: Yakalanmamış bir yerel değişkenin aksine, yakalanan bir yerel değişken aynı anda birden çok yürütme iş parçacığına maruz kalabilir. son notu

12.21.6.3 Yerel değişkenlerin örneklemesi

Bir yerel değişken, yürütme değişkenin kapsamına girdiğinde oluşturulmuş kabul edilir.

Örnek: Örneğin, aşağıdaki yöntem çağrıldığında, x yerel değişkeni döngünün her yinelemesinde oluşturulur ve üç kez başlatılır.

static void F()
{
    for (int i = 0; i < 3; i++)
    {
        int x = i * 2 + 1;
        ...
    }
}

Ancak, x bildiriminin döngü dışına taşınması, x'in tek bir kez örneklenmesine yol açar.

static void F()
{
    int x;
    for (int i = 0; i < 3; i++)
    {
        x = i * 2 + 1;
        ...
    }
}

son örnek

Yakalanmadığında, bir yerel değişkenin tam olarak ne sıklıkta örneklendiğine dikkat etmenin bir yolu yoktur; örneklemelerin yaşam süreleri kopuk olduğundan, her örneklemenin aynı depolama konumunu kullanması mümkündür. Ancak, anonim bir işlev yerel bir değişkeni yakaladığında, örneklemenin etkileri görünür hale gelir.

Örnek: Örnek

delegate void D();
class Test
{
    static D[] F()
    {
        D[] result = new D[3];
        for (int i = 0; i < 3; i++)
        {
            int x = i * 2 + 1;
            result[i] = () => Console.WriteLine(x);
        }
        return result;
    }

    static void Main()
    {
        foreach (D d in F())
        {
            d();
        }
    }
}

çıktıyı üretir:

1
3
5

Ancak, x bildirimi döngünün dışına taşındığında:

delegate void D();

class Test
{
    static D[] F()
    {
        D[] result = new D[3];
        int x;
        for (int i = 0; i < 3; i++)
        {
            x = i * 2 + 1;
            result[i] = () => Console.WriteLine(x);
        }
        return result;
   }

   static void Main()
   {
       foreach (D d in F())
       {
           d();
       }
   }
}

çıkış şöyledir:

5
5
5

Bir derleyicinin üç örneklemeyi tek bir temsilci örneğinde (§10.7.2) iyileştirmesine izin verildiğini (ancak gerekli olmadığını) unutmayın.

son örnek

Bir for-döngüsü bir yineleme değişkeni olarak bildirirse, bu değişkenin kendisi döngü dışında bildirileceği kabul edilir.

Örnek: Bu nedenle, yineleme değişkeninin kendisini yakalamak için örnek değiştirilirse:

delegate void D();

class Test
{
    static D[] F()
    {
        D[] result = new D[3];
        for (int i = 0; i < 3; i++)
        {
            result[i] = () => Console.WriteLine(i);
        }
        return result;
   }

   static void Main()
   {
       foreach (D d in F())
       {
           d();
       }
   }
}

Yineleme değişkeninin yalnızca bir örneği yakalanır ve bu da çıkışı üretir:

3
3
3

son örnek

Anonim işlev temsilcilerinin yakalanan bazı değişkenleri paylaşması ancak diğerlerinin ayrı örneklerine sahip olması mümkündür.

Örnek: Örneğin, F olarak değiştirilirse

static D[] F()
{
    D[] result = new D[3];
    int x = 0;
    for (int i = 0; i < 3; i++)
    {
        int y = 0;
        result[i] = () => Console.WriteLine($"{++x} {++y}");
    }
    return result;
}

üç temsilci aynı x örneğini yakalar ancak yörneklerini ayırır ve çıkış şöyle olur:

1 1
2 1
3 1

son örnek

Ayrı anonim işlevler dış değişkenin aynı örneğini yakalayabilir.

Örnek: Bu örnekte:

delegate void Setter(int value);
delegate int Getter();

class Test
{
    static void Main()
    {
        int x = 0;
        Setter s = (int value) => x = value;
        Getter g = () => x;
        s(5);
        Console.WriteLine(g());
        s(10);
        Console.WriteLine(g());
    }
}

iki anonim işlev xyerel değişkenin aynı örneğini yakalar ve böylece bu değişken aracılığıyla "iletişim kurabilir". Örneğin çıktısı:

5
10

son örnek

12.21.7 Anonim işlev ifadelerinin değerlendirilmesi

Anonim bir işlev F, daima doğrudan veya bir temsilci oluşturma ifadesi D'nin yürütülmesi yoluyla E bir temsilci türüne veya new D(F)bir ifade ağacı türüne dönüştürülmelidir. Bu dönüştürme, §10.7bölümünde açıklandığı gibi anonim işlevin sonucunu belirler.

12.21.8 Uygulama Örneği

Bu alt bildirim bilgilendiricidir.

Bu alt bölüm, diğer C# yapıları açısından anonim işlev dönüştürmelerinin olası bir uygulamasını açıklar. Burada açıklanan uygulama, ticari bir C# derleyicisi tarafından kullanılan ilkeleri temel alır, ancak hiçbir şekilde zorunlu bir uygulama değildir ve mümkün olan tek uygulama da değildir. Tam semantikleri bu belirtim kapsamının dışında olduğundan ifade ağaçlarına dönüştürmelerden yalnızca kısa bir süre bahseder.

Bu alt başlığın geri kalanında farklı özelliklere sahip anonim işlevler içeren birkaç kod örneği verilmiştir. Her örnek için, yalnızca diğer C# yapılarını kullanan koda karşılık gelen bir çeviri sağlanır. Örneklerde, tanımlayıcı D aşağıdaki temsilci türünü temsil ettiği varsayılır:

public delegate void D();

Anonim bir işlevin en basit biçimi, dış değişken yakalamaz:

delegate void D();

class Test
{
    static void F()
    {
        D d = () => Console.WriteLine("test");
    }
}

Bu, anonim işlevin kodunun yerleştirildiği derleyici tarafından oluşturulan statik yönteme başvuran bir temsilci örneklemesine çevrilebilir:

delegate void D();

class Test
{
    static void F()
    {
        D d = new D(__Method1);
    }

    static void __Method1()
    {
        Console.WriteLine("test");
    }
}

Aşağıdaki örnekte anonim işlev thisörnek üyelerine başvurur:

delegate void D();

class Test
{
    int x;

    void F()
    {
        D d = () => Console.WriteLine(x);
    }
}

Bu, anonim işlevin kodunu içeren derleyici tarafından oluşturulan bir örnek yöntemine çevrilebilir:

delegate void D();

class Test
{
   int x;

   void F()
   {
       D d = new D(__Method1);
   }

   void __Method1()
   {
       Console.WriteLine(x);
   }
}

Bu örnekte anonim işlev bir yerel değişken yakalar:

delegate void D();

class Test
{
    void F()
    {
        int y = 123;
        D d = () => Console.WriteLine(y);
    }
}

Yerel değişkenin ömrü artık en az anonim işlev temsilcisinin ömrüne uzatılmalıdır. Bu, yerel değişkenin derleyici tarafından oluşturulan bir sınıfın alanına "hoisting" ile taşınmasıyla elde edilebilir. Yerel değişkenin (§12.21.6.3) örneği, derleyici tarafından oluşturulan sınıfın bir örneğini oluşturmaya karşılık gelir ve yerel değişkene erişmek, derleyici tarafından oluşturulan sınıfın örneğindeki bir alana erişmeye karşılık gelir. Ayrıca anonim işlev, derleyici tarafından oluşturulan sınıfın örnek yöntemi haline gelir:

delegate void D();

class Test
{
    void F()
    {
        __Locals1 __locals1 = new __Locals1();
        __locals1.y = 123;
        D d = new D(__locals1.__Method1);
    }

    class __Locals1
    {
        public int y;

        public void __Method1()
        {
            Console.WriteLine(y);
        }
    }
}

Son olarak, aşağıdaki anonim işlev this ve farklı yaşam süresine sahip iki yerel değişkeni yakalar:

delegate void D();

class Test
{
   int x;

   void F()
   {
       int y = 123;
       for (int i = 0; i < 10; i++)
       {
           int z = i * 2;
           D d = () => Console.WriteLine(x + y + z);
       }
   }
}

Burada, yerel değişkenlerin yakalandığı her blok için derleyici tarafından bir sınıf oluşturulur, böylece farklı bloklardaki yerel değişkenler bağımsız yaşam sürelerine sahip olabilir. İç blok için derleyici tarafından oluşturulan sınıf olan __Locals2örneği, z yerel değişkenini ve __Locals1örneğine başvuran bir alanı içerir. Dış blok için derleyici tarafından oluşturulan sınıf olan bir __Locals1örneği, yerel değişken y ve kapsayan işlev üyesinin this'sine referans veren bir alan içerir. Bu veri yapılarıyla, __Local2örneği aracılığıyla yakalanan tüm dış değişkenlere ulaşmak mümkündür ve anonim işlevin kodu bu sınıfın örnek yöntemi olarak uygulanabilir.

delegate void D();

class Test
{
    int x;

    void F()
    {
        __Locals1 __locals1 = new __Locals1();
        __locals1.__this = this;
        __locals1.y = 123;
        for (int i = 0; i < 10; i++)
        {
            __Locals2 __locals2 = new __Locals2();
            __locals2.__locals1 = __locals1;
            __locals2.z = i * 2;
            D d = new D(__locals2.__Method1);
        }
    }

    class __Locals1
    {
        public Test __this;
        public int y;
    }

    class __Locals2
    {
        public __Locals1 __locals1;
        public int z;

        public void __Method1()
        {
            Console.WriteLine(__locals1.__this.x + __locals1.y + z);
        }
    }
}

Yerel değişkenleri yakalamak için burada uygulanan aynı teknik, anonim işlevleri ifade ağaçlarına dönüştürürken de kullanılabilir: derleyici tarafından oluşturulan nesnelere başvurular ifade ağacında depolanabilir ve yerel değişkenlere erişim bu nesnelerde alan erişimi olarak gösterilebilir. Bu yaklaşımın avantajı, "kaldırılan" yerel değişkenlerin temsilciler ve ifade ağaçları arasında paylaşılmasına izin vermesidir.

Bilgilendirici metin sonu.

12.22 Sorgu ifadeleri

12.22.1 Genel

Sorgu ifadeleri SQL ve XQuery gibi ilişkisel ve hiyerarşik sorgu dillerine benzeyen sorgular için dille tümleşik bir söz dizimi sağlar.

query_expression
    : from_clause query_body
    ;

from_clause
    : 'from' type? identifier 'in' expression
    ;

query_body
    : query_body_clause* select_or_group_clause query_continuation?
    ;

query_body_clause
    : from_clause
    | let_clause
    | where_clause
    | join_clause
    | join_into_clause
    | orderby_clause
    ;

let_clause
    : 'let' identifier '=' expression
    ;

where_clause
    : 'where' boolean_expression
    ;

join_clause
    : 'join' type? identifier 'in' expression 'on' expression
      'equals' expression
    ;

join_into_clause
    : 'join' type? identifier 'in' expression 'on' expression
      'equals' expression 'into' identifier
    ;

orderby_clause
    : 'orderby' orderings
    ;

orderings
    : ordering (',' ordering)*
    ;

ordering
    : expression ordering_direction?
    ;

ordering_direction
    : 'ascending'
    | 'descending'
    ;

select_or_group_clause
    : select_clause
    | group_clause
    ;

select_clause
    : 'select' expression
    ;

group_clause
    : 'group' expression 'by' expression
    ;

query_continuation
    : 'into' identifier query_body
    ;

Sorgu ifadesi bir from yan tümcesiyle başlar ve select veya group yan tümcesiyle biter. İlk from yan tümcesinin ardından sıfır veya daha fazla from, let, where, join veya orderby yan tümceleri gelebilir. Her from yan tümcesi, bir dizisinin öğeleriüzerinde değişen bir aralığı değişkeni tanıtan bir oluşturucudur. Her let yan tümcesi, önceki aralık değişkenleri yoluyla hesaplanan bir değeri temsil eden bir aralık değişkeni sunar. Her where yan tümcesi, öğeleri sonuçtan dışlayan bir filtredir. Her join yan tümcesi, kaynak dizinin belirtilen anahtarlarını başka bir dizinin anahtarlarıyla karşılaştırır ve eşleşen çiftleri verir. Her orderby yan tümcesi öğeleri belirtilen ölçütlere göre yeniden sıralar. Son select veya group yan tümcesi, aralık değişkenleri açısından sonucun şeklini belirtir. Son olarak, bir into yan tümcesi, bir sorgunun sonuçlarını sonraki sorguda üreteç olarak değerlendirerek sorguları "birleştirmek" için kullanılabilir.

12.22.2 Sorgu ifadelerindeki belirsizlikler

Sorgu ifadeleri bir dizi bağlamsal anahtar sözcük kullanır (§6.4.4): ascending, by, descending, equals, from, group, into, join, let, on, orderby, select ve where.

Bu tanımlayıcıların hem anahtar sözcükler hem de basit adlar olarak kullanılmasından kaynaklanabilecek belirsizlikleri önlemek için, bu tanımlayıcıların ön ekinde "@" (§6.4.4) olmadığı sürece, bu tanımlayıcılar sorgu ifadesinin herhangi bir yerinde anahtar sözcükler olarak kabul edilir. Bu amaçla, sorgu ifadesi " ""tanımlayıcısı " ile başlayan ve ardından "", " "" veya "" dışında herhangi bir belirteç içeren herhangi bir ifadedir.

12.22.3 Sorgu ifadesi çevirisi

12.22.3.1 Genel

C# dili, sorgu ifadelerinin yürütme semantiğini belirtmez. Bunun yerine, sorgu ifadeleri sorgu-ifade desenine (§12.22.4) bağlı olan yöntemlerin çağrılarına çevrilir. Özellikle, sorgu ifadeleri Where, Select, SelectMany, Join, GroupJoin, OrderBy, OrderByDescending, ThenBy, ThenByDescending, GroupByve Castadlı yöntemlerin çağrılarına çevrilir. Bu yöntemlerin , §12.22.4'te açıklandığı gibi belirli imzalara ve dönüş türlerine sahip olması beklenir. Bu yöntemler sorgulanan nesnenin örnek yöntemleri veya nesnenin dışındaki uzantı yöntemleri olabilir. Bu yöntemler sorgunun gerçek yürütmesini uygular.

Sorgu ifadelerinden yöntem çağrılarına çeviri, herhangi bir tür bağlaması veya aşırı yükleme çözümlemesi gerçekleştirilmeden önce gerçekleşen söz dizimsel bir eşlemedir. Sorgu ifadelerinin çevirisinin ardından, sonuçta elde edilen yöntem çağrıları normal yöntem çağrıları olarak işlenir ve bu da derleme zamanı hatalarını ortaya çıkarabilir. Bu hata koşulları, var olmayan yöntemleri, yanlış türlerin bağımsız değişkenlerini ve tür çıkarımının başarısız olduğu genel yöntemleri içerir ancak bunlarla sınırlı değildir.

Sorgu ifadesi, daha fazla azaltma mümkün olmayana kadar aşağıdaki çeviriler tekrar tekrar uygulanarak işlenir. Çeviriler uygulama sırasına göre listelenir: Her bölüm, önceki bölümlerdeki çevirilerin kapsamlı bir şekilde gerçekleştirildiğini varsayar ve tükendikten sonra aynı sorgu ifadesinin işlenmesinde bir bölüm yeniden ziyaret edilmeyecektir.

Bir sorgu ifadesinin bir aralık değişkenine atama eklemesi veya bir aralık değişkeninin başvuru veya çıkış parametresi için bağımsız değişken olarak kullanılması derleme zamanı hatasıdır.

Bazı çeviriler, * ile belirtilen saydam tanımlayıcılarla aralık değişkenlerini ekler. Bunlar daha ayrıntılı olarak §12.22.3.8'de açıklanmıştır.

12.22.3.2 Süreklilik içeren ifadeleri sorgulama

Sorgu gövdesini takip eden devamlılığı olan bir sorgu ifadesi

from «x1» in «e1» «b1» into «x2» «b2»

olarak çevrilir

from «x2» in ( from «x1» in «e1» «b1» ) «b2»

Aşağıdaki bölümlerdeki çevirilerde sorguların devamı olmadığı varsayılır.

Örnek: Örnek:

from c in customers
group c by c.Country into g
select new { Country = g.Key, CustCount = g.Count() }

şu şekilde çevrilir:

from g in
   (from c in customers
   group c by c.Country)
select new { Country = g.Key, CustCount = g.Count() }

son çevirisi:

customers.
GroupBy(c => c.Country).
Select(g => new { Country = g.Key, CustCount = g.Count() })

son örnek

12.22.3.3 Açık aralık değişken türleri

Açıkça bir aralık değişkeni türünü belirten bir from yan tümcesi

from «T» «x» in «e»

olarak çevrilir

from «x» in ( «e» ) . Cast < «T» > ( )

Açıkça bir aralık değişkeni türünü belirten bir join yan tümcesi

join «T» «x» in «e» on «k1» equals «k2»

olarak çevrilir

join «x» in ( «e» ) . Cast < «T» > ( ) on «k1» equals «k2»

Aşağıdaki bölümlerdeki çevirilerde sorguların açık aralık değişken türleri olmadığı varsayılır.

Örnek: Örnek

from Customer c in customers
where c.City == "London"
select c

olarak çevrilir

from c in (customers).Cast<Customer>()
where c.City == "London"
select c

son çevirisi

customers.
Cast<Customer>().
Where(c => c.City == "London")

son örnek

Not: Açık aralık değişken türleri, genel olmayan IEnumerable arabirimini uygulayan koleksiyonları sorgulamak için yararlıdır, ancak genel IEnumerable<T> arabirimini kullanmaz. Yukarıdaki örnekte, müşteriler ArrayListtüründeyse bu durum geçerli olacaktır. son notu

12.22.3.4 Bozuk sorgu ifadeleri

Formun sorgu ifadesi

from «x» in «e» select «x»

olarak çevrilir

( «e» ) . Select ( «x» => «x» )

Örnek: Örnek

from c in customers
select c

olarak çevrilir

(customers).Select(c => c)

son örnek

Bozuk sorgu ifadesi, kaynağın öğelerini önemsiz bir şekilde seçen ifadedir.

Not: Çevirinin sonraki aşamaları (§12.22.3.6 ve §12.22.3.7) diğer çeviri adımları tarafından tanıtılan bozuk sorguları kaynaklarıyla değiştirerek kaldırır. Ancak, sorgu ifadesinin sonucunun hiçbir zaman kaynak nesnenin kendisi olmaması önemlidir. Aksi takdirde, böyle bir sorgunun sonucunu döndürmek istemeden çağırana özel verileri (örneğin, bir öğe dizisi) açığa çıkarabilir. Bu nedenle bu adım, kaynak kodda açıkça Select çağırarak doğrudan kaynak koduna yazılan bozuk sorguları korur. Daha sonra bu yöntemlerin kaynak nesnenin kendisini hiçbir zaman döndürmediğinden emin olmak Select ve diğer sorgu işleçlerinin uygulayıcılarına bağlıdır. son notu

12.22.3.5 Kimden, let, where, join ve orderby yan tümceleri

İkinci bir from yan tümcesi ve ardından bir select yan tümcesi içeren sorgu ifadesi

from «x1» in «e1»  
from «x2» in «e2»  
select «v»

olarak çevrilir

( «e1» ) . SelectMany( «x1» => «e2» , ( «x1» , «x2» ) => «v» )

Örnek: Örnek

from c in customers
from o in c.Orders
select new { c.Name, o.OrderID, o.Total }

olarak çevrilir

(customers).
SelectMany(c => c.Orders,
(c,o) => new { c.Name, o.OrderID, o.Total }
)

son örnek

İkinci bir from yan tümcesi ve ardından boş olmayan sorgu gövdesi yan tümceleri içeren bir sorgu gövdesi Q olan sorgu ifadesi:

from «x1» in «e1»
from «x2» in «e2»
Q

olarak çevrilir

from * in («e1») . SelectMany( «x1» => «e2» ,
                              ( «x1» , «x2» ) => new { «x1» , «x2» } )
Q

Örnek: Örnek

from c in customers
from o in c.Orders
orderby o.Total descending
select new { c.Name, o.OrderID, o.Total }

olarak çevrilir

from * in (customers).
   SelectMany(c => c.Orders, (c,o) => new { c, o })
orderby o.Total descending
select new { c.Name, o.OrderID, o.Total }

son çevirisi

customers.
SelectMany(c => c.Orders, (c,o) => new { c, o }).
OrderByDescending(x => x.o.Total).
Select(x => new { x.c.Name, x.o.OrderID, x.o.Total })

burada x, başka türlü görünmez ve erişilemez derleyici tarafından oluşturulan bir tanımlayıcıdır.

son örnek

Bir let ifadesi ve önceki from yan tümcesiyle birlikte.

from «x» in «e»  
let «y» = «f»  
...

olarak çevrilir

from * in ( «e» ) . Select ( «x» => new { «x» , «y» = «f» } )  
...

Örnek: Örnek

from o in orders
let t = o.Details.Sum(d => d.UnitPrice * d.Quantity)
where t >= 1000
select new { o.OrderID, Total = t }

olarak çevrilir

from * in (orders).Select(
    o => new { o, t = o.Details.Sum(d => d.UnitPrice * d.Quantity) })
where t >= 1000
select new { o.OrderID, Total = t }

son çevirisi

orders
    .Select(o => new { o, t = o.Details.Sum(d => d.UnitPrice * d.Quantity) })
    .Where(x => x.t >= 1000)
    .Select(x => new { x.o.OrderID, Total = x.t })

burada x, başka türlü görünmez ve erişilemez derleyici tarafından oluşturulan bir tanımlayıcıdır.

son örnek

Bir where ifadesi ve önceki from yan tümcesiyle birlikte.

from «x» in «e»  
where «f»  
...

olarak çevrilir

from «x» in ( «e» ) . Where ( «x» => «f» )  
...

Bir join yan tümcesinin hemen ardından bir select yan tümcesi

from «x1» in «e1»  
join «x2» in «e2» on «k1» equals «k2»  
select «v»

olarak çevrilir

( «e1» ) . Join( «e2» , «x1» => «k1» , «x2» => «k2» , ( «x1» , «x2» ) => «v» )

Örnek: Örnek

from c in customers
join o in orders on c.CustomerID equals o.CustomerID
select new { c.Name, o.OrderDate, o.Total }

olarak çevrilir

(customers).Join(
   orders,
   c => c.CustomerID, o => o.CustomerID,
   (c, o) => new { c.Name, o.OrderDate, o.Total })

son örnek

Bir join maddesi, ardından sorgu gövdesi takip eder:

from «x1» in «e1»  
join «x2» in «e2» on «k1» equals «k2»  
...

olarak çevrilir

from * in ( «e1» ) . Join(  
«e2» , «x1» => «k1» , «x2» => «k2» ,
( «x1» , «x2» ) => new { «x1» , «x2» })  
...

join - into yan tümcesinin hemen ardından bir select yan tümcesi

from «x1» in «e1»  
join «x2» in «e2» on «k1» equals «k2» into «g»  
select «v»

olarak çevrilir

( «e1» ) . GroupJoin( «e2» , «x1» => «k1» , «x2» => «k2» ,
                     ( «x1» , «g» ) => «v» )

Bir join into yan tümcesi ve ardından sorgu gövdesi yan tümcesi

from «x1» in «e1»  
join «x2» in «e2» on «k1» equals «k2» into *g»  
...

olarak çevrilir

from * in ( «e1» ) . GroupJoin(  
   «e2» , «x1» => «k1» , «x2» => «k2» , ( «x1» , «g» ) => new { «x1» , «g» })
...

Örnek: Örnek

from c in customers
join o in orders on c.CustomerID equals o.CustomerID into co
let n = co.Count()
where n >= 10
select new { c.Name, OrderCount = n }

olarak çevrilir

from * in (customers).GroupJoin(
    orders,
    c => c.CustomerID,
    o => o.CustomerID,
    (c, co) => new { c, co })
let n = co.Count()
where n >= 10
select new { c.Name, OrderCount = n }

son çevirisi

customers
    .GroupJoin(
        orders,
        c => c.CustomerID,
        o => o.CustomerID,
        (c, co) => new { c, co })
    .Select(x => new { x, n = x.co.Count() })
    .Where(y => y.n >= 10)
    .Select(y => new { y.x.c.Name, OrderCount = y.n })

Derleyici tarafından oluşturulan ve diğer türlü görünmez ve erişilemez olan tanımlayıcılar x ve y'dir.

son örnek

Bir orderby yan tümcesi ve onu önceleyen from yan tümcesi:

from «x» in «e»  
orderby «k1» , «k2» , ... , «kn»  
...

olarak çevrilir

from «x» in ( «e» ) .
OrderBy ( «x» => «k1» ) .
ThenBy ( «x» => «k2» ) .
... .
ThenBy ( «x» => «kn» )
...

ordering yan tümcesi azalan bir yön göstergesi belirtirse, bunun yerine OrderByDescending veya ThenByDescending çağrısı gerçekleştirilir.

Örnek: Örnek

from o in orders
orderby o.Customer.Name, o.Total descending
select o

son çeviriye sahip

(orders)
    .OrderBy(o => o.Customer.Name)
    .ThenByDescending(o => o.Total)

son örnek

Aşağıdaki çevirilerde, let, where, join veya orderby yan tümceleri olmadığı ve her sorgu ifadesinde tek bir ilk from yan tümcesi olmadığı varsayılır.

12.22.3.6 Select yan tümceleri

Formun sorgu ifadesi

from «x» in «e» select «v»

olarak çevrilir

( «e» ) . Select ( «x» => «v» )

«v», tanımlayıcı «x»olduğunda dışında, çeviri yalnızca

( «e» )

Örnek: Örnek

from c in customers.Where(c => c.City == "London")
select c

basitçe çevrilir

(customers).Where(c => c.City == "London")

son örnek

12.22.3.7 Grup yan tümceleri

group yan tümcesi

from «x» in «e» group «v» by «k»

olarak çevrilir

( «e» ) . GroupBy ( «x» => «k» , «x» => «v» )

«v» tanımlayıcı «x»olduğu durumlar hariç, çeviri

( «e» ) . GroupBy ( «x» => «k» )

Örnek: Örnek

from c in customers
group c.Name by c.Country

olarak çevrilir

(customers).GroupBy(c => c.Country, c => c.Name)

son örnek

12.22.3.8 Saydam tanımlayıcılar

Bazı çeviriler, tarafından belirtilen aralık değişkenlerini ekler. Saydam tanımlayıcılar yalnızca sorgu-ifade çevirisi işleminde bir ara adım olarak bulunur.

Sorgu çevirisi bir saydam tanımlayıcı eklediğinde, diğer çeviri adımları saydam tanımlayıcıyı anonim işlevlere ve anonim nesne başlatıcılara yayar. Bu bağlamlarda saydam tanımlayıcılar aşağıdaki davranışlara sahiptir:

  • Saydam tanımlayıcı anonim bir işlevde parametre olarak gerçekleştiğinde, ilişkili anonim türün üyeleri anonim işlevin gövdesindeki kapsamda otomatik olarak yer alır.
  • Saydam tanımlayıcısı olan bir üye kapsam içinde olduğunda, bu üyenin üyeleri de kapsamda olur.
  • Saydam bir tanımlayıcı anonim nesne başlatıcıda üye bildirimcisi olarak gerçekleştiğinde, saydam tanımlayıcısı olan bir üyeyi tanıtır.

Yukarıda açıklanan çeviri adımlarında, saydam tanımlayıcılar her zaman tek bir nesnenin üyesi olarak birden çok aralık değişkeni yakalama amacıyla anonim türlerle birlikte tanıtılır. C# uygulamasının birden çok aralık değişkenini gruplandırmak için anonim türlerden farklı bir mekanizma kullanmasına izin verilir. Aşağıdaki çeviri örneklerinde anonim türlerin kullanıldığı varsayılır ve saydam tanımlayıcıların olası bir çevirisi gösterilir.

Örnek: Örnek

from c in customers
from o in c.Orders
orderby o.Total descending
select new { c.Name, o.Total }

olarak çevrilir

from * in (customers).SelectMany(c => c.Orders, (c,o) => new { c, o })
orderby o.Total descending
select new { c.Name, o.Total }

daha ileri çevrilen

customers
    .SelectMany(c => c.Orders, (c,o) => new { c, o })
    .OrderByDescending(* => o.Total)
    .Select(\* => new { c.Name, o.Total })

saydam tanımlayıcılar silindiğinde, eşdeğerdir

customers
    .SelectMany(c => c.Orders, (c,o) => new { c, o })
    .OrderByDescending(x => x.o.Total)
    .Select(x => new { x.c.Name, x.o.Total })

burada x, başka türlü görünmez ve erişilemez derleyici tarafından oluşturulan bir tanımlayıcıdır.

Örnek

from c in customers
join o in orders on c.CustomerID equals o.CustomerID
join d in details on o.OrderID equals d.OrderID
join p in products on d.ProductID equals p.ProductID
select new { c.Name, o.OrderDate, p.ProductName }

olarak çevrilir

from * in (customers).Join(
    orders,
    c => c.CustomerID,
    o => o.CustomerID,
    (c, o) => new { c, o })
join d in details on o.OrderID equals d.OrderID
join p in products on d.ProductID equals p.ProductID
select new { c.Name, o.OrderDate, p.ProductName }

daha da azaltılır

customers
    .Join(orders, c => c.CustomerID,
        o => o.CustomerID, (c, o) => new { c, o })
    .Join(details, * => o.OrderID, d => d.OrderID, (*, d) => new { *, d })
    .Join(products, * => d.ProductID, p => p.ProductID,
        (*, p) => new { c.Name, o.OrderDate, p.ProductName })

son çevirisi

customers
    .Join(orders, c => c.CustomerID,
        o => o.CustomerID, (c, o) => new { c, o })
    .Join(details, x => x.o.OrderID, d => d.OrderID, (x, d) => new { x, d })
    .Join(products, y => y.d.ProductID, p => p.ProductID,
        (y, p) => new { y.x.c.Name, y.x.o.OrderDate, p.ProductName })

Derleyici tarafından oluşturulan ve diğer türlü görünmez ve erişilemez olan tanımlayıcılar x ve y'dir. son örnek

12.22.4 Sorgu-ifade düzeni

Query-expression deseni, sorgu ifadelerini desteklemek için türlerin uygulayabileceği bir yöntem deseni oluşturur.

Genel üye yöntemleri ve genel olarak erişilebilen uzantı yöntemleri aşağıdaki sınıf tanımıyla değiştirilebiliyorsa, genel bir tür C<T> sorgu-ifade-deseni'ni destekler. Üyeler ve erişilebilir uzantı yöntemleri, genel bir türün C<T>"şekli" olarak adlandırılır. Genel tür, parametre ve dönüş türleri arasındaki doğru ilişkileri göstermek için kullanılır, ancak genel olmayan türler için de deseni uygulamak mümkündür.

delegate R Func<T1,R>(T1 arg1);
delegate R Func<T1,T2,R>(T1 arg1, T2 arg2);

class C
{
    public C<T> Cast<T>() { ... }
}

class C<T> : C
{
    public C<T> Where(Func<T,bool> predicate) { ... }
    public C<U> Select<U>(Func<T,U> selector) { ... }
    public C<V> SelectMany<U,V>(Func<T,C<U>> selector,
        Func<T,U,V> resultSelector) { ... }
    public C<V> Join<U,K,V>(C<U> inner, Func<T,K> outerKeySelector,
        Func<U,K> innerKeySelector, Func<T,U,V> resultSelector) { ... }
    public C<V> GroupJoin<U,K,V>(C<U> inner, Func<T,K> outerKeySelector,
        Func<U,K> innerKeySelector, Func<T,C<U>,V> resultSelector) { ... }
    public O<T> OrderBy<K>(Func<T,K> keySelector) { ... }
    public O<T> OrderByDescending<K>(Func<T,K> keySelector) { ... }
    public C<G<K,T>> GroupBy<K>(Func<T,K> keySelector) { ... }
    public C<G<K,E>> GroupBy<K,E>(Func<T,K> keySelector,
        Func<T,E> elementSelector) { ... }
}

class O<T> : C<T>
{
    public O<T> ThenBy<K>(Func<T,K> keySelector) { ... }
    public O<T> ThenByDescending<K>(Func<T,K> keySelector) { ... }
}

class G<K,T> : C<T>
{
    public K Key { get; }
}

Yukarıdaki yöntemler Func<T1, R> ve Func<T1, T2, R>genel temsilci türlerini kullanır, ancak parametre ve dönüş türlerinde aynı ilişkilere sahip diğer temsilci veya ifade ağacı türlerini de aynı şekilde kullanmış olabilirler.

Not: C<T> ile O<T> arasındaki önerilen ilişki, ThenBy ve ThenByDescending yöntemlerinin yalnızca bir OrderBy veya OrderByDescendingsonucunda kullanılabilir olmasını sağlar. son notu

Not: her iç sıranın ek bir GroupBy özelliğine sahip olduğu dizi dizisi olan Keysonucunun önerilen şekli. son notu

Not: Sorgu ifadeleri söz dizimli eşleme yoluyla yöntem çağrılarına çevrildiğinden, türlerin sorgu ifadesi deseninin herhangi birini veya tümünü uygulama konusunda önemli bir esnekliği vardır. Örneğin, desenin yöntemleri örnek yöntemleri veya uzantı yöntemleri olarak uygulanabilir çünkü ikisi de aynı çağırma söz dizimine sahiptir ve yöntemler temsilciler veya ifade ağaçları isteyebilir çünkü anonim işlevler her ikisine de dönüştürülebilir. Sorgu ifadesi deseninin yalnızca bir kısmını uygulayan türler, yalnızca uygun yöntemlere eşleyen sorgu ifadesi dönüşümlerini destekler. son notu

Not: System.Linq ad alanı, System.Collections.Generic.IEnumerable<T> arabirimini uygulayan her tür için sorgu-ifade deseninin bir uygulamasını sağlar. son notu

12.23 Atama işleçleri

12.23.1 Genel

Atama işleçlerinden biri dışında tümü bir değişkene, özelliğe, olaya veya dizin oluşturucu öğesine yeni bir değer atar. = refözel durumu, bir referans değişkenine (§9,5) bir referans değişkeni atar (§9,7).

assignment
    : unary_expression assignment_operator expression
    ;

assignment_operator
    : '=' 'ref'? | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
      '<<=' | '??='
    | right_shift_assignment
    ;

Atamanın sol işleneni, değişken olarak sınıflandırılan bir ifade ya da = refhariç olmak üzere bir özellik erişimi, dizinleyici erişimi, olay erişimi veya tuple olmalıdır. Bir bildirim ifadesine doğrudan sol işlenen olarak izin verilmez, ancak bir yapısızlaştırma ataması değerlendirilirken bir adım olarak oluşabilir.

işleci,basit atama işleci olarak adlandırılır. Sağ işlenenin değerini veya değerlerini, sol işlenen tarafından verilen değişkene, özelliğe, dizin öğesine veya demet öğelerine atar. Basit atama işlecinin sol işleneni, §15.8.2'de açıklandığı durumlar dışında, olay erişimi olmamalıdır. Basit atama işleci §12.23.2'de açıklanmıştır.

İşleç = ref, başvuru atama işleciolarak adlandırılır. Sağ işlenen, variable_reference (§9.5) olarak sol işleneni belirler ve bu referans değişkenin hedefi yapar. Başvuru atama işleci §12.23.3'te açıklanmıştır.

ve = işleci dışındaki = ref atama işleçleri bileşik atama işleciolarak adlandırılır. Bu işleçler aşağıdaki gibi işlenir:

  • ??= operatörü için, yalnızca sol operatörün değeri null ise sağ operatör değerlendirilir ve elde edilen sonuç, sol operatör tarafından belirtilen değişken, özellik veya dizinleyici öğesine atanır.
  • Aksi takdirde, belirtilen işlem iki işlenende gerçekleştirilir ve ardından sonuçta elde edilen değer, sol işlenen tarafından verilen değişkene, özelliğe veya dizin oluşturucu öğesine atanır. Bileşik atama işleçleri §12.23.4'te açıklanmıştır.

+= Sol işlenen olarak bir olay erişim ifadesi olan ve -= işleçleri, olay atama işleciolarak adlandırılır. Sol işlenen olarak etkinlik erişimi olduğunda, başka hiçbir atama işleci geçerli değildir. Olay atama işleçleri §12.23.5'te açıklanmıştır.

Atama işleçleri sağdan sola doğru ilişkilendirilir, yani işlemler sağdan sola gruplandırılır.

Örnek: Form a = b = c ifadesi a = (b = c)olarak değerlendirilir. son örnek

12.23.2 Basit atama

= işleci basit atama işleci olarak adlandırılır.

Basit bir atamanın sol işleneni, E.P'nin derleme zamanı türü E[Ei]ise ve formu E veya dynamic şeklindeyse, atama dinamik olarak bağlıdır (§12.3.3). Bu durumda, atama ifadesinin derleme anındaki türü dynamic'dır ve aşağıda açıklanan çözüm, E'in çalışma zamanı türüne bağlı olarak çalışma anında gerçekleşecektir. Sol işlenen, E[Ei] en az bir öğesinin Eiderleme zamanı türüne sahip olduğu ve dynamic derleme zamanı türünün bir dizi olmadığı formunda olan E ise, sonuçta elde edilen dizin oluşturucu erişimi dinamik olarak bağlanır, ancak sınırlı derleme zamanı denetimiyle (§12.6.5).

Soldaki işlenenin demet olarak sınıflandırıldığı basit bir atama, ayrıcayapısöküm ataması olarak da adlandırılır. Sol işlenenin grup öğelerinden herhangi biri bir öğe adına sahipse, derleme zamanında hata oluşur. Sol işlenenin asal öğelerinden herhangi biri bildirim ifadesi ve diğer herhangi bir öğe bildirim ifadesi veya basit bir atma değilse, derleme zamanı hatası oluşur.

Basit bir atama olan x = y türü, x'nin y'e atama türüdür ve bu tür özyinelemeli olarak aşağıdaki gibi belirlenir.

  • x bir demet ifadesiyse, ve (x1, ..., xn)y öğeleriyle ((y1, ..., yn)) bir demet ifadesi olarak deşifre edilebiliyorsa, ve n'nın 'e yapılan her ataması xi türüne sahipse, bu atama yi türüne sahiptir.
  • Aksi takdirde, x bir değişken olarak sınıflandırılırsa, değişkeni readonlydeğildir xTtürüne sahiptir ve yT'a örtük bir dönüştürmesi vardır ve atamanın türü Tolur.
  • Aksi takdirde, x örtük olarak tanımlanan bir değişken (örtük bildirim ifadesi) olarak sınıflandırılırsa ve y, türü Tolan bir değişkense, değişkenin çıkarılmış türü Tve atama Ttürüne sahiptir.
  • Aksi takdirde, x bir özellik veya dizin erişimi olarak sınıflandırılırsa, bu özellik veya dizin erişilebilir bir ayar işlevine sahipse, xTtüründeyse ve y'ün T'e örtük bir dönüşümü varsa, atama Ttüründe olur.
  • Aksi takdirde atama geçerli değildir ve bağlama zamanı hatası oluşur.

Tür x = y ile T formunda basit bir atamanın çalışma zamanındaki işlenmesi, xtürüne sahip y'ü, T'ye atama olarak gerçekleştirilir ve bu işlem, aşağıdaki özyinelemeli adımlardan oluşur.

  • Eğer henüz değerlendirilmediyse, x değerlendirilir.
  • x değişken olarak sınıflandırılırsa, y değerlendirilir ve gerekirse örtük dönüştürme yoluyla T dönüştürülür (§10.2).
    • x tarafından verilen değişken bir reference_typedizi öğesiyse, y için hesaplanan değerin x öğe olduğu dizi örneğiyle uyumlu olduğundan emin olmak için bir çalışma zamanı denetimi gerçekleştirilir. y nullise veya 'ün başvurduğu örneğinin türünden, y'i içeren dizi örneğinin gerçek öğe türüne dair bir örtük başvuru dönüşümü (x) varsa denetim başarılı olur. Aksi takdirde, bir System.ArrayTypeMismatchException fırlatılır.
    • y değerlendirmesi ve dönüşümünden elde edilen değer, xdeğerlendirmesi tarafından verilen konuma depolanır ve atamanın sonucu olarak verilir.
  • x özellik veya dizin oluşturucu erişimi olarak sınıflandırılmışsa:
    • y değerlendirilir ve gerekirse örtük dönüştürme yoluyla T dönüştürülür (§10.2).
    • x set erişimcisi, y'in değerlendirilmesi ve dönüştürülmesi sonucunda elde edilen değer, değer bağımsız değişkeni olarak çağrılır.
    • y değerlendirmesi ve dönüşümünden elde edilen değer, atamanın sonucu olarak elde edilir.
  • x, (x1, ..., xn)arity'sine sahip bir demet n olarak sınıflandırılırsa:
    • y, n öğeleriyle eadlı bir demet ifadesi olarak parçalanmıştır.
    • örtük bir demet dönüştürmesi kullanılarak t'in e'ye dönüştürülmesi ile bir sonuç demeti T oluşturulur.
    • Soldan sağa doğru her xi için, xi yeniden değerlendirilmediğinden, t.Itemixi'e atanır.
    • Atamanın sonucu olarak t elde edilir.

Not: Eğer x'nin derleme zamanı türü dynamic ise ve y'ün derleme zamanı türünden dynamic'e bir örtük dönüştürme varsa, çalışma zamanı çözümlemesi gerekmez. son notu

Not: Dizi ortak varyans kuralları (§17.6), A[]'dan B[]'ye örtük bir başvuru dönüştürmesinin mevcut olması koşuluyla, B dizi türündeki bir değerin Adizi türünün bir örneğine başvuru olmasına izin verir. Bu kurallar nedeniyle, bir reference_type dizi öğesine atama, atanan değerin dizi örneğiyle uyumlu olduğundan emin olmak için bir çalışma zamanı denetimi gerektirir. Örnekte

string[] sa = new string[10];
object[] oa = sa;
oa[0] = null;              // OK
oa[1] = "Hello";           // OK
oa[2] = new ArrayList();   // ArrayTypeMismatchException

son atama, bir System.ArrayTypeMismatchException başvurusunun bir ArrayListöğesinde depolanamaması nedeniyle bir string[] fırlatılmasına neden olur.

son notu

bir struct_type bildirilen bir özellik veya dizin oluşturucu bir atamanın hedefi olduğunda, özellik veya dizin oluşturucu erişimiyle ilişkili örnek ifadesi değişken olarak sınıflandırılır. Örnek ifadesi bir değer olarak sınıflandırılırsa, bağlama zamanı hatası oluşur.

Not: §12.8.7nedeniyle, aynı kural alanlar için de geçerlidir. son notu

Örnek: Bildirimlere göre:

struct Point
{
   int x, y;

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

   public int X
   {
      get { return x; }
      set { x = value; }
   }

   public int Y {
      get { return y; }
      set { y = value; }
   }
}

struct Rectangle
{
    Point a, b;

    public Rectangle(Point a, Point b)
    {
        this.a = a;
        this.b = b;
    }

    public Point A
    {
        get { return a; }
        set { a = value; }
    }

    public Point B
    {
        get { return b; }
        set { b = value; }
    }
}

örnekte

Point p = new Point();
p.X = 100;
p.Y = 100;
Rectangle r = new Rectangle();
r.A = new Point(10, 10);
r.B = p;

p.X ve p.Y değişken olduğundan, r.A, r.B, pve r atamalarına izin verilir. Ancak örnekte

Rectangle r = new Rectangle();
r.A.X = 10;
r.A.Y = 10;
r.B.X = 100;
r.B.Y = 100;

r.A ve r.B değişken olmadığından atamaların tümü geçersizdir.

son örnek

12.23.3 Başvuru ataması

= ref işleci, referans atama işleci olarak bilinir.

Sol operand, bir başvuru değişkenine (§9.7), bir başvuru parametresine (thishariç), bir çıkış parametresine veya bir giriş parametresine bağlanan bir ifade olmalıdır. Sağ işlenen, sol işlenenle aynı türde bir değer belirten bir variable_reference veren bir ifade olacaktır.

Sol işlenenin "ref-safe-context" (§9.7.2) değeri sağ işleneninkinden daha genişse, bu durumda bir derleme zamanı hatası oluşur.

Sağ işlenen, ref ataması noktasında kesinlikle atanmış olmalıdır.

Sol işlenen bir çıkış parametresine bağlandığında, eğer bu çıkış parametresi ref atama işlecinin başlangıcında kesin olarak atanmış değilse, bu bir hatadır.

Sol işlenen yazılabilir bir başvuruysa (yani, ref readonly yerel veya giriş parametresi dışında bir şey belirtir), sağ işlenen yazılabilir bir variable_referenceolmalıdır. Eğer sağ operant değişkeni yazılabiliyorsa, sol operant yazılabilir veya salt okunur bir başvuru türü olabilir.

İşlem, sol işleneni sağ işlenen değişkenin bir takma adı olarak yapar. Sağ operand değişkeni yazılabilir olsa bile diğer ad salt okunur hale getirilebilir.

Referans atama işleci, atanan türün variable_reference oluşturur. Sol işlenen yazılabilir durumda ise yazılabilir.

Referans atama operatörü, sağdaki operand tarafından başvurulan depolama konumunu okumaz.

Örnek: = refkullanmanın bazı örnekleri aşağıda verilmiştir:

public static int M1() { ... }
public static ref int M2() { ... }
public static ref uint M2u() { ... }
public static ref readonly int M3() { ... }
public static void Test()
{
int v = 42;
ref int r1 = ref v; // OK, r1 refers to v, which has value 42
r1 = ref M1();      // Error; M1 returns a value, not a reference
r1 = ref M2();      // OK; makes an alias
r1 = ref M2u();     // Error; lhs and rhs have different types
r1 = ref M3();    // error; M3 returns a ref readonly, which r1 cannot honor
ref readonly int r2 = ref v; // OK; make readonly alias to ref
r2 = ref M2();      // OK; makes an alias, adding read-only protection
r2 = ref M3();      // OK; makes an alias and honors the read-only
r2 = ref (r1 = ref M2());  // OK; r1 is an alias to a writable variable,
              // r2 is an alias (with read-only access) to the same variable
}

son örnek

Not: = ref işlecini kullanarak kod okurken, işlenenin parçası olarak ref bölümünü okumak cazip olabilir. İşlenen bir koşullu ?: ifadesi olduğunda bu özellikle kafa karıştırıcıdır. Örneğin, ref int a = ref b ? ref x : ref y; okurken, bunu işleç olarak = ref ve sağ operand olarak b ? ref x : ref y şeklinde okumak önemlidir: ref int a = ref (b ? ref x : ref y);. Daha da önemlisi, ref b ifadesi ilk bakışta bu şekilde görünse de bu deyimin bir parçası değildir. son notu

12.23.4 Bileşik atama

Bileşik atamalar, sol operatörü E.P derleme zamanı türünün E[Ei]olduğu biçimde E veya dynamic ise, atama dinamik olarak bağlanır (§12.3.3). Bu durumda, atama ifadesinin derleme anındaki türü dynamic'dır ve aşağıda açıklanan çözüm, E'in çalışma zamanı türüne bağlı olarak çalışma anında gerçekleşecektir. Sol işlenen, E[Ei] en az bir öğesinin Eiderleme zamanı türüne sahip olduğu ve dynamic derleme zamanı türünün bir dizi olmadığı formunda olan E ise, sonuçta elde edilen dizin oluşturucu erişimi dinamik olarak bağlanır, ancak sınırlı derleme zamanı denetimiyle (§12.6.5).

a ??= b, (T) (a ?? (a = b)) ile eşdeğerdir, ancak a yalnızca bir kez değerlendirilir; T türü dinamik olduğunda a türü b, aksi takdirde T türü a ?? b türüdür.

Aksi takdirde, bir işlem x «op»= y şekline sahipse, bu işlem olarak yazılmış gibi ikili işleç aşırı yükleme çözümlemesiyle (x «op» y) işlenir. Ardından

  • Seçilen işlecin dönüş türü, xtürüne örtük olarak dönüştürülebiliyorsa, x = x «op» y sadece bir kez değerlendirilmesi hariç, işlem xolarak değerlendirilir.
  • Aksi takdirde, seçili işleç önceden tanımlanmış bir işleçse, seçilen işlecin dönüş türü açıkça x türüne dönüştürülebilirse ve yx türüne örtük olarak dönüştürülebilirse veya işleç bir shift işleciyse, işlem x = (T)(x «op» y)olarak değerlendirilir; burada Txtürüdür. ancak x yalnızca bir kez değerlendirilir.
  • Aksi takdirde, bileşik atama geçersizdir ve bağlama zamanı hatası oluşur.

"Yalnızca bir kez değerlendirildi" terimi, x «op» ydeğerlendirmesinde x tüm kurucu ifadelerinin sonuçlarının geçici olarak kaydedildiği ve xataması yapılırken yeniden kullanıldığı anlamına gelir.

Örnek: A()[B()] += C()görevinde, Aint[]döndüren bir yöntemdir ve B ve Cintdöndüren yöntemlerdir. Yöntemler yalnızca bir kez, A, B, Csırasıyla çağrılır. son örnek

Bileşik atamanın sol işleneni bir özellik erişimi veya dizin oluşturucu erişimi olduğunda, özellik veya dizin oluşturucu hem get erişimcisine hem de set erişimcisine sahip olmalıdır. Bu durum böyle değilse, bir bağlama zamanı hatası oluşur.

Yukarıdaki ikinci kural, x «op»= y belirli bağlamlarda x = (T)(x «op» y) olarak değerlendirilmesine izin verir. Kural, önceden tanımlanmış işleçlerin sol işlenen sbyte, byte, short, ushortveya chartüründe olduğunda bileşik işleçler olarak kullanılabilmesi için vardır. Her iki bağımsız değişken de bu türlerden birinde olsa bile, önceden tanımlanmış işleçler§12.4.7.3'te açıklandığı gibi türünde bir sonuç üretir. Bu nedenle, tür dönüşümü olmadan sonucu sol işlemciye atamak mümkün olmaz.

Kuralın, önceden tanımlanmış işleçler için sezgisel etkisi basitçe şudur: Hem x «op»= y'e hem de x «op» y'ye izin verilirse, x = y'a da izin verilir.

Örnek: Aşağıdaki kodda

byte b = 0;
char ch = '\0';
int i = 0;
b += 1;           // OK
b += 1000;        // Error, b = 1000 not permitted
b += i;           // Error, b = i not permitted
b += (byte)i;     // OK
ch += 1;          // Error, ch = 1 not permitted
ch += (char)1;    // OK

her hatanın sezgisel nedeni, karşılık gelen basit atamanın da hata olmasıdır.

son örnek

Not: Bu, bileşik atama işlemlerinin kaldırılmış operatörleri desteklediği anlamına da gelir. Bileşik atama x «op»= y, x = x «op» y veya x = (T)(x «op» y)olarak değerlendirildiğinden, değerlendirme kuralları örtük olarak kaldırılmış işleçleri kapsar. son notu

12.23.5 Olay ataması

Eğer a += or -= işlecinin sol işleneni olay erişimi olarak sınıflandırılıyorsa, ifade aşağıdaki gibi değerlendirilir:

  • Olay erişiminin örnek ifadesi (varsa) değerlendirilir.
  • += veya -= işlecinin sağ işleneni değerlendirilir ve gerekirse sol işlenenin türüne örtük bir dönüştürme ile dönüştürülür (§10.2).
  • Bir olay erişimcisi, önceki adımda hesaplanan değerden oluşan bir bağımsız değişken listesiyle çağrılır. İşleç +=ise ekleme erişimcisi çağrılır; işleci -=ise kaldırma erişimcisi çağrılır.

Olay atama ifadesi bir değer vermez. Bu nedenle, olay atama ifadesi yalnızca bir statement_expression (§13.7) bağlamında geçerlidir.

12.24 İfadesi

ifadesi ya bir atama_dışı_ifade ya da bir atama.

expression
    : non_assignment_expression
    | assignment
    ;

non_assignment_expression
    : declaration_expression
    | conditional_expression
    | lambda_expression
    | query_expression
    ;

12.25 Sabit ifadeleri

Sabit ifade, derleme zamanında tam olarak değerlendirilecek bir ifadedir.

constant_expression
    : expression
    ;

Sabit ifadenin değeri null veya aşağıdaki türlerden birine sahip olmalıdır:

  • sbyte, byte, short, ushort, int, uint, long, ulong, char, float, doubledecimal, boolstring;
  • bir numaralandırma türü; veya
  • bir başvuru türü için varsayılan değer ifadesi (§12.8.21).

Sabit ifadelerde yalnızca aşağıdaki yapılara izin verilir:

  • Sabitler (null sabiti dahil).
  • Sınıf, yapı ve arabirim türlerinin üyelerine başvurular const .
  • Enum tipi üyelerine referanslar.
  • Yerel sabitlere başvurular.
  • Kendilerinin sabit ifadeleri olan parantezli alt ifadeler.
  • Tür ifadeleri.
  • checked ve unchecked ifadeleri.
  • nameof ifadeleri.
  • Önceden tanımlanmış +, -, ! (mantıksal olumsuzlama) ve ~ tekli işleçler.
  • Önceden tanımlanmış +, -, *, /, %, <<, >>, &, |, ^, &&, ||, ==, !=, <, >, <=ve >= ikili işleçleri.
  • ?: koşullu işleci.
  • ! null-forgiving işleci (§12.8.9).
  • sizeofifadeleri, yönetilmeyen türü için sabit değer döndüren sizeof içinde belirtilen türlerden biri olması koşuluyla.
  • Türün yukarıda listelenen türlerden biri olması koşuluyla varsayılan değer ifadeleri.

Sabit ifadelerde aşağıdaki dönüştürmelere izin verilir:

  • Kimlik dönüştürmeleri
  • Sayısal dönüştürmeler
  • Sıralama Dönüştürmeleri
  • Sabit ifade dönüştürmeleri
  • Örtük ve açık başvuru dönüşümleri, dönüştürmelerin kaynağı null değerini değerlendiren sabit bir ifade olduğu sürece mümkündür.

Not:null olmayan değerlerin kutulama, kutu açma ve örtük başvuru dönüştürmeleri gibi diğer dönüştürmelere sabit ifadelerde izin verilmez. son notu

Örnek: Aşağıdaki kodda

class C
{
    const object i = 5;         // error: boxing conversion not permitted
    const object str = "hello"; // error: implicit reference conversion
}

i'ın başlatılması, bir kutulama dönüşümü gerektiği için hatalıdır. str'ın başlatılması,null olmayan bir değerden örtük bir başvuru dönüşümü gerektiği için hatadır.

son örnek

Bir ifade yukarıda listelenen gereksinimleri karşılıyorsa, ifade derleme zamanında değerlendirilir. Bu, ifade sabit olmayan yapılar içeren daha büyük bir ifadenin alt ifadesi olsa bile geçerlidir.

Sabit ifadelerin derleme zamanı değerlendirmesi, sabit olmayan ifadelerin çalışma zamanı değerlendirmesiyle aynı kuralları kullanır, ancak çalışma zamanı değerlendirmesi özel durum oluşturacağı durumlarda derleme zamanı değerlendirmesi derleme zamanı hatası oluşmasına neden olur.

Sabit bir ifade açıkça bir unchecked bağlamına yerleştirilmediği sürece, tamsayı türünde aritmetik işlemler ve ifadelerin derleme zamanında değerlendirilmesi sırasında gerçekleşen taşmalar ve dönüştürmeler her zaman derleme zamanı hatalarına neden olur (§12.8.20).

Sabit ifadeler aşağıda listelenen bağlamlarda gereklidir ve bu, constant_expressionkullanılarak dil bilgisi içinde gösterilir. Bu bağlamlarda, bir ifade derleme zamanında tam olarak değerlendirilemiyorsa derleme zamanı hatası oluşur.

  • Sabit bildirimler (§15.4)
  • Numaralandırma üyesi bildirimleri (§20.4)
  • Parametre listelerinin varsayılan bağımsız değişkenleri (§15.6.2)
  • case etiketleri switch ifadesi (§13.8.3).
  • goto case ifadeler (§13.10.4)
  • Başlatıcı içeren bir dizi oluşturma ifadesindeki (§12.8.17.4) boyut uzunlukları.
  • Öznitelikler (§23)
  • Bir constant_pattern (§11.2.3) içinde

Örtük sabit ifade dönüştürmesi (§10.2.11), sabit ifadenin değeri hedef türün aralığında olması koşuluyla int türündeki sabit bir ifadenin sbyte, byte, short, ushort, uintveya ulongdönüştürülmesini sağlar.

12.26 Boole ifadeleri

boolean_expression, booltüründe bir sonuç veren bir ifadedir; doğrudan veya aşağıdaki gibi belirli bağlamlarda operator true uygulaması aracılığıyla:

boolean_expression
    : expression
    ;

Bir if_statement (§13.8.2), while_statement (§13.9.2), do_statement (§13.9.3) veya for_statement (§13.9.4) denetimsel koşul ifadesi boolean_ifadesi'dir. İşlecin denetimli koşullu ifadesi ?: (§12.20) bir boolean_expression ile aynı kurallara uyar, ancak işleç önceliği nedeniyle null_coalescing_expression olarak sınıflandırılır.

aşağıdaki gibi türünde bir değer üretebilmek için bir Ebool gereklidir:

  • E'nin örtük olarak bool'a dönüştürülebilmesi durumunda, çalışma zamanında o örtük dönüştürme uygulanır.
  • Aksi takdirde, tekli işleç aşırı yükleme çözümlemesi (§12.4.4), operator trueüzerinde en iyi tekil E çözümünü bulmak için kullanılır ve bu çözüm çalışma zamanında uygulanır.
  • Böyle bir işleç bulunmazsa bağlama zamanı hatası oluşur.