Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
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
thistarafı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 sonucuthistarafı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,
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,
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ı
Ö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.WriteLineiç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.WriteLineaşı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
+,-,*,/venewverilebilir. İş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öntemFeskiideğeri kullanılarak çağrılır, ardından yöntemGeskiideğeriyle çağrılır ve son olarak yöntemHyeni 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 * zişleci ikilix + (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.yx?.yf(x)a[x]a?[x]x++x--x!newtypeofdefaultcheckeduncheckeddelegatestackalloc§12.9 Tekli +-!x~^++x--x(T)xawait 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 <><=>=isas§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..zhem hemx..(y..z)de..geçersizdir. son örnek
Öncelik ve ilişkisellik parantezler kullanılarak denetlenebilir.
Örnek:
x + y * zönceyilezçarpar ve ardından sonucuxekler, ancak(x + y) * zöncexveyekler ve ardından sonucuzile ç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
trueifadelerde açıkça kullanılmasafalseda (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
isveyaasiş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 birboolsonucu 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
Xiçinoperator «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
XiçinYveoperator «op»(x, y)tarafından sağlanan aday kullanıcı tanımlı işleç kümesi belirlenir. Küme, her biriXkuralları kullanılarak belirlenen,Ytarafı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:-
XveYkimlik dönüştürülebilirse veyaXveYortak bir temel türden türetilmişse, paylaşılan aday işleçleri birleştirilmiş kümede yalnızca bir kez gerçekleşir. -
XileYarasında bir kimlik dönüşümü varsa,«op»Ytarafından sağlananYişleci,«op»Xtarafından sağlananXile aynı dönüş türüne sahip olur ve«op»Y'nın işlenen türleri, karşılık gelen«op»Xişlenen türlerine kimlik dönüşümüne sahiptir ve kümede yalnızca«op»Xoluş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.Tnull atanabilir bir değer türüyse,T₀onun temel türüdür; aksi takdirde,T₀,Tile eşittir. -
operator «op»'deki tümT₀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ümesiT₀'deki ilgili tüm işleçlerden oluşur. - Aksi takdirde,
T₀ileobjecteş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ı veyaT₀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 * sbirbvebyte'insolduğushortişlemi için, aşırı yükleme çözümlemesi en iyi işleç olarakoperator *(int, int)'yi seçer. Sonuç olarak, etki,bves'inint'ye dönüştürülmesi ve sonucun türününintolmasıdır. Benzer şekilde,i * dişlemi için,ibirintvedbirdoubleolduğunda,overloadçözünürlük en iyi işleç olarakoperator *(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şlenendecimaltürüne dönüştürülür veya diğer işlenenfloatveyadoubletüründeyse bağlama zamanı hatası oluşur. - Aksi takdirde, işlenenlerden biri
doubletüründeyse, diğer işlenendoubletürüne dönüştürülür. - Aksi takdirde, işlenenlerden biri
floattüründeyse, diğer işlenenfloattürüne dönüştürülür. - Aksi takdirde, işlenenlerden biri
ulongtüründeyse, diğer işlenenulongtürüne dönüştürülür veya diğer işlenentype sbyte,short,intveyalongise bağlama zamanı hatası oluşur. - Aksi takdirde, işlenenlerden biri
longtüründeyse, diğer işlenenlongtürüne dönüştürülür. - Aksi takdirde, işlenenlerden biri
uinttüründeyse ve diğer işlenensbyte,shortveyainttüründeyse, her iki işlenen delongtürüne dönüştürülür. - Aksi takdirde, işlenenlerden biri
uinttüründeyse, diğer işlenenuinttürüne dönüştürülür. - Aksi takdirde, her iki işlenen de
inttürüne dönüştürülür.
Not: İlk kural,
decimaltürünüdoublevefloattürleriyle karıştıran işlemlere izin vermemektedir. Kural,decimaltürü iledoublevefloattü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
ulongtüründe olması mümkün değildir. Bunun nedeni, hemulong'ı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
decimalbirdoubleile çarpılamadığından bağlama zamanı hatası oluşur. Hata, ikinci işleneni aşağıdaki gibi açıkçadecimal'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şlenennullise, kaldırılan işleç birnulldeğ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 ikisinullise birnulldeğer üretir (&açıklandığı gibi türün|vebool?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ç ikinulldeğerini eşit kabul eder venulldeğerininullolmayan 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 veboolsonucunu ü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 defalseisenulldeğerini üretir. Aksi takdirde, yükseltilmiş operatör işlenenleri açar ve temel operatörü uygulayarakboolsonucunu ü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,
Nadlı bir erişilebilir üye kümesi belirlenir:-
Tbir tür parametresiyse, küme,Niçin birincil kısıtlama veya ikincil kısıtlama (§15.2.5) olarak belirtilen türlerin her birindeTadlı erişilebilir üye kümelerinin veNiçindeobjectadlı erişilebilir üye kümesinin birleşimidir. - Aksi takdirde, küme, devralınan üyeler ve içinde
Nadlı erişilebilir üyeler de dahil olmak üzere,TiçindeNadlı tüm erişilebilir (object) üyelerinden oluşur.Tyapı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.overridedeğiştiricisi içeren üyeler kümenin dışında tutulur.
-
- Ardından,
Ksıfırsa, bildirimleri tür parametrelerini içeren tüm iç içe türler kaldırılır.Ksıfır değilse, farklı sayıda tür parametresine sahip tüm üyeler kaldırılır.Ksı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.Miçin,Süyesinin bildirildiği türM'dir ve aşağıdaki kurallar uygulanır:-
Msabit, alan, özellik, olay veya numaralandırma üyesiyse, temelStüründe bildirilen tüm üyeler kümeden kaldırılır. -
Mbir tür bildirimiyse, temelStüründe bildirilen tüm tür dışı türler kümeden kaldırılır veMtemel türünde bildirilenSile aynı sayıda tür parametresine sahip tüm tür bildirimleri kümeden kaldırılır. -
Mbir yöntemse, temelStü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
Tbir tür parametresiyse veThemobjectdışında etkili bir temel sınıfa hem de boş olmayan etkin arabirim kümesine (§15.2.5) sahipse geçerlidir. Kümedeki her üyeS.Miçin,S, üyeM'nin bildirildiği tür olduğunda, eğerS,objectdışında bir sınıf bildirimi ise aşağıdaki kurallar uygulanır:-
Msabit, alan, özellik, olay, numaralandırma üyesi veya tür bildirimiyse, arabirim bildiriminde bildirilen tüm üyeler kümeden kaldırılır. -
Mbir yöntemse, arabirim bildiriminde bildirilen tüm yöntem dışı üyeler kümeden kaldırılır ve arabirim bildiriminde bildirilenMile 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.
-
TobjectveyadynamiciseT'ün temel türü olmaz. -
Tbir enum_typeise,T'ün temel türleriSystem.Enum,System.ValueTypeveobjectsınıf türleridir. -
Tbir struct_typeise, temelTtürleriSystem.ValueTypeveobjectsınıf türleridir.Notu: bir nullable_value_type, bir struct_type'tir (§8.3.1). son notu
-
Tbir class_typeise,T'ün temel türleri,Tsınıf türü dahilobject'ün temel sınıflarıdır. -
Tbir arabirim_türüise,Ttemel türleri,T'ün temel arabirimleri veobjectsınıf türüdür. -
Tbir array_typeise, temelTtürleriSystem.Arrayveobjectsınıf türleridir. -
Tbir delegate_typeise, temelTtürleriSystem.Delegateveobjectsı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,yvevaluedeğişken veya değer olarak sınıflandırılan ifadeleri gösterirTtür olarak sınıflandırılan bir ifadeyi gösterir,Fbir yöntemin basit adıdır vePö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 Fen 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öntemistaticdeğilse, örnek ifadesithis.T.F(x, y)Sınıf veya yapı Fiçinde en iyi yöntemT'ı seçmek için aşırı yükleme çözümlemesi uygulanır. yöntemistaticdeğ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 arabirimdeeen iyi yöntemi seçmek için uygulanır. yöntemistaticolduğ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.Pyalnızca yazılabilir olduğunda derleme zamanı hatası oluşur.Pstaticdeğilse, örnek ifadesithisolur.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ı,Psalt okunur olduğunda oluşur.Pstaticdeğilse, örnek ifadesithisolur.T.PSınıf veya yapı PiçindekiTözelliğinin al erişimcisi çağrıldı.Pstaticdeğilse ya daPsadece 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.Pstaticdeğilse veyaPsalt okunursa derleme zamanı hatası oluşur.e.PPtürü tarafından verilen sınıf, yapı veya arabirimdeEözellik erişimcisi,eörnek ifadesiyle çağrılır.Pstaticolduğunda veyaPyalnızca yazılabilir olduğunda bağlama zamanı hatası oluşur.e.P = valuePtürü tarafından verilen sınıf, yapı veya arabirimde, örnek ifadesiEve bağımsız değişken listesieile özellik(value)'ın set erişimcisi çağrılır.P,staticise veyaPsalt okunursa bağlama zamanı hatası oluşur.Etkinlik erişimi E += valueIçeren sınıf veya yapıda olay Eekleme erişimcisi çağrılır.Estaticdeğilse, örnek ifadesithisolur.E -= valueİçeren sınıf veya yapıda olay Eiçin remove erişimcisi çağrılır.Estaticdeğilse, örnek ifadesithisolur.T.E += valueOlay E'nın sınıf veya yapıT'deki ekleme erişimcisi çağrılır.Estaticdeğilse bağlama zamanı hatası oluşur.T.E -= valueSınıf veya yapı Eiçindeki olayT'ın kaldırma erişimcisi çağrıldı.Estaticdeğilse bağlama zamanı hatası oluşur.e.E += valueEtürü tarafından belirlenen sınıf, yapı veya arabirimdekiEolayının ekleme erişimcisi,eörnek ifadesiyle çağrılır.Estaticolduğunda bağlama zamanı hatası oluşur.e.E -= valueEtürü tarafından verilen sınıf, yapı veya arabirimdekiEolayının kaldırma erişimcisi,eörnek ifadesiyle çağrılır.Estaticolduğ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 ifadesieve 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] = valueAşı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 -xAşırı yükleme çözümlemesi, xtü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 + yAşırı yükleme çözümlemesi, xveytü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.
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
valueparametresine 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, ancakcadlı 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 argumentM1(i)yöntem çağrısında,ikendisi 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ürint'ye sahiptir.M1(i + 5)yöntem çağrısında adsız birintdeğ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.2ve §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.ArrayTypeMismatchExceptionatı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übolduğu vestringolmadığı için birobjecthatası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 = 3son ö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,
intvestringtü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şkenleriXₑ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şkeniXᵢ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
12.6.3.5 Çıkış türleri
Eğer
12.6.3.6 Bağımlılığı
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:
-
EArity ve öğeleriNolan bir tanımlama grubu ifadesi (Eᵢ) ise veTkarşılık gelen öğe türlerineNsahip arityTₑiçeren bir tanımlama grubu türüyse veyaTnull atanabilir bir değer türüyseT0?veT0karşılık gelen öğe türüne sahip bir tanımlamaNgrubu türüyseTₑ, herEᵢbiri için giriş türü çıkarımı öğesindenEᵢTₑyapılır. - Anonim bir işlevse
E, açık parametre türü çıkarımı (§12.6.3.9)ET - Aksi takdirde, türü
EvarsaUve 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ü
EvarsaUve 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ü
EvarsaUve karşılık gelen parametre bir giriş parametresi (§15.6.2.3.2) veEbir giriş bağımsız değişkeniyse, tam çıkarım (§12.6.3.10) öğesindenUT - Aksi takdirde, türü
EvarsaUve 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:
-
EarityNve öğeleriEᵢolan bir tanımlama grubu ifadesiyse veTkarşılık gelen öğe türlerineNsahip bir tanımlamaTₑgrubu türüyse veyaTnull atanabilir bir değer türüyseT0?veT0karşılık gelen öğe türüne sahip arityNdeğerine sahip bir tanımlama grubu türüyseTₑ, herEᵢbir çıkış türü çıkarımı öğesindenEᵢTₑyapılır. - Çıkarsanan dönüş türüne
E(U) sahip anonim bir işlevse veTdönüş türüneTₓ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ᵥveTparametre türlerineV₁...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 gelenVᵢöğ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:
-
VsabitlenmemişXᵢbiriyse,Uiçin tam sınır kümesineXᵢeklenir. - Aksi takdirde,
V₁...VₑveU₁...Uₑkümeleri, aşağıdaki durumlardan birinin geçerli olup olmadığını denetleyerek belirlenir:-
Vbir dizi türüV₁[...]veUaynı dereceye sahip bir dizi türüU₁[...] -
V,V₁?türü olup,UiseU₁türüdür. -
V, bir yapılandırılmış türdürC<V₁...Vₑ>veU, bir yapılandırılmış türdürC<U₁...Uₑ>
Bu durumlardan herhangi biri geçerliyse, her bir 'den ilgiliUᵢ'e kadarVᵢyapılır.
-
- Aksi takdirde çıkarım yapılmaz.
12.6.3.11 Alt sınır çıkarımları
Bir tür
- Eğer
V, sabitlenmemişXᵢ’den biri ise,U,Xᵢiçin alt sınırlar kümesine eklenir. - Aksi takdirde,
VtürüV₁?veUtürüU₁?ise,U₁'denV₁'e daha düşük bir sınır çıkarımı yapılır. - Aksi takdirde,
U₁...UₑveV₁...Vₑkümeleri, aşağıdaki durumlardan birinin geçerli olup olmadığını denetleyerek belirlenir:-
Vbir dizi türüV₁[...]veUaynı dereceye sahip bir dizi türüU₁[...] -
VIEnumerable<V₁>,ICollection<V₁>,IReadOnlyList<V₁>>,IReadOnlyCollection<V₁>veyaIList<V₁>biridir veUtek boyutlu bir dizi türüdürU₁[] -
V,class,struct,interfaceveyadelegatetürü oluşturulmuş birC<V₁...Vₑ>'tir veC<U₁...Uₑ>,U(veya,Ubirparametertürüyse, etkin temel sınıfı veya etkin arabirim kümesinin herhangi bir üyesi) ile aynı olan, doğrudan veya dolaylı olarakinherits'dan türemiş veyaC<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>{}UveyaC<T>olabileceğinden,U₁'denX'a çıkarılırkenYarabirimde çıkarım yapılmadığı anlamına gelir.)
Bu durumlardan herhangi biri geçerliyse, her birUᵢ'dan ilgiliVᵢ'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,
Ubir 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ımi-th'ünCtü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:
-
VsabitlenmemişXᵢbiriyse,Uiçin üst sınır kümesineXᵢeklenir. - Aksi takdirde,
V₁...VₑveU₁...Uₑkümeleri, aşağıdaki durumlardan birinin geçerli olup olmadığını denetleyerek belirlenir:-
Ubir dizi türüU₁[...]veVaynı dereceye sahip bir dizi türüV₁[...] -
UIEnumerable<Uₑ>,ICollection<Uₑ>,IReadOnlyList<Uₑ>,IReadOnlyCollection<Uₑ>veyaIList<Uₑ>biridir veVtek boyutlu bir dizi türüdürVₑ[] -
U,U1?türü olup,ViseV1?türüdür. -
U,C<U₁...Uₑ>türündeki bir sınıf, yapı, arayüz veya temsilcidir veVclass, struct, interfaceveyadelegatetüründedir. Bu tür doğrudan veya dolaylı olarakidenticaltürüneinherits'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₁>'denV<Q>'ye çıkarım yapılmadığı anlamına gelir.U₁'denX<Q>'e veyaY<Q>'e çıkarım yapılmaz.)
Bu durumlardan herhangi biri geçerliyse, her birUᵢ'dan ilgiliVᵢ'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,
Vbir dizi türüyse üst sınır çıkarımı yapılır - Aksi takdirde, eğer
UC<U₁...Uₑ>ise, çıkarımi-th'ünCtü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 birXᵢkesin sınırı U için,Uₑile özdeş olmayan tümUtü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ümUtü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ümUtü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
Fgövdesi bir türü olan ifadesi ise, o zamanF'nin belirlenmiş etkin dönüş türü o ifadenin türüdür. - gövdesi
Fbir bloksa ve bloğunreturndeyimlerindeki ifade kümesi en iyi ortak türeT(§12.6.3.16) sahipse, çıkarılmış etkin dönüş türüFolurT. - Aksi takdirde,
Fiçin etkili bir dönüş türü çıkarılamaz.
çıkarımlı dönüş türü aşağıdaki gibi belirlenir:
-
Fasenkron ise veFgö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üreturnolur («TaskType»). - Eğer
Fasenkron ise veTçıkarılmış etkin dönüş türüne sahipse, çıkarılmış dönüş türü«TaskType»<T>»(§15.14.1) olur. -
Fuyumsuz değilse ve çıkarılmış etkin dönüş türüTise, çıkarsanan dönüş türüTolur. - Aksi takdirde,
Fiçin bir dönüş türü çıkarılamaz.
Örnek: Anonim işlevleri içeren tür çıkarımı örneği olarak,
Selectsınıfında bildirilenSystem.Linq.Enumerableuzantı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.Linqad alanının birusing namespaceyönergesi ile içeri aktarıldığı veCustomertüründeNameözelliğine sahip bir sınıfstringverildiği varsayıldığında,Selectyö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'ınCustomerolduğu çıkarımı yapılmaktadır. Ardından, yukarıda açıklanan anonim işlev türü çıkarım işlemi kullanılarakctürüCustomerverilir vec.Nameifadesi seçici parametresinin dönüş türüyle ilişkilendirilerek,TResult'ünstringolduğ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'ınstringolduğu çıkartılır. Ardından, ilk anonim işlevin parametresisiçin çıkarılan türstringolarak verilir veTimeSpan.Parse(s)ifadesi,f1'ün dönüş türü ile ilişkilendirilerek,Y'ünSystem.TimeSpanolduğu sonucu çıkarılır. Son olarak, ikinci anonim işlevin parametresit'e, belirlenen türSystem.TimeSpanverilir vet.TotalHoursifadesi,f2dönüş türüyle ilişkilendirilir veZ'ündoubleolduğu belirlenir. Bu nedenle, çağırmanın sonucudoubletü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ᵥ>
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
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
Xkullanıma sunulmuştur. - Her ifade
Eiiçin bir çıkış türü çıkarımı (§12.6.3.8) ondan öğesineXgerçekleştirilir. -
Xmü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 kullanarakEᵢyöntemini çağırmak veXsonucunu çı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
indeğ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
indeğ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,
- 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ı
Atoplam 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şkenin parametre geçirme modu, karşılık gelen parametrenin parametre geçirme moduyla aynıdır ve:
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
thiserişime izin verildiğinde uygulanabilir §12.8.14.
- Yöntem grubu bir simple_namesonucu verirse, örnek yöntemi yalnızca
- 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ᵥ'danQᵥ'e olan örtük dönüşüm,Eᵥ'denPᵥ'e olan örtük dönüşümden daha iyi değildir ve - en az bir argüman için,
Eᵥ'danPᵥ'e dönüşüm,Eᵥ'denQᵥ'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 veMₑgenel bir yöntemse,MᵢMₑ'den daha iyidir. - Aksi takdirde,
Mᵢnormal biçiminde uygulanıyorsa veMₑ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 dizisindeMₑ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ᵥveMₓ'nin belirtilmemiş ve genişletilmemiş parametre türlerini temsil eder.Mᵥparametre türleri, her parametre içinMₓRx'den daha az özel değilseSx'den daha belirgindir ve en az bir parametre içinRxSx'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şkenlerinMₓ'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 veMₓ'daki parametrelerin hiçbiriMᵥ'den daha iyi parametre geçirme seçeneğini kullanmıyorsaMᵥ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:
-
ET₁tam olarak eşleşir veET₂tam olarak eşleşmez (§12.6.4.6) -
E, ya hemT₁hem deT₂ile tam olarak eşleşir ya da hiçbiriyle eşleşmez veT₁,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) veC₁dönüştürmeT₂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:
-
EStürüne sahiptir veS'denT'e bir kimlik dönüşümü vardır -
Eanonim bir işlevdir,TDtemsilci türü veyaExpression<D>ifade ağacı türüdür ve aşağıdakilerden biridir:- parametre listesi
X(E) bağlamında içinDbir çıkarsanan dönüş türü vardır ve 'denXdönüş türüne bir kimlik dönüştürmesi vardırD -
E, dönüş değeri olmayan birasynclambdadır veDgenel olmayan bir«TaskType»dönüş türüne sahiptir - Ya
Esenkron değildir veDdönüş türüneYsahiptir ya daEasenkron olupDdönüş türüne«TaskType»<Y>(§15.14.1) sahiptir ve aşağıdakilerden biri geçerlidir:-
Eiçeriği,Yile tam olarak eşleşen bir ifadedir -
Egövdesi, her return deyimininYile aynı olan bir ifade döndürdüğü bir bloktur.
-
- parametre listesi
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₁'danT₂'ye örtük dönüştürme mevcut veT₂'danT₁'e örtük dönüştürme yok -
T₁is«TaskType»<S₁>(§15.14.1),T₂is«TaskType»<S₂>, veS₁,S₂'den daha iyi bir dönüştürme hedefidir. -
T₁olur«TaskType»<S₁>(§15.14.1),T₂olur«TaskType»<S₂>veT₁daha uzmanT₂ -
T₁,S₁'ün imzalı bir tam sayı türü olduğu durundaS₁?veyaS₁'dir veT₂,S₂'nin işaretsiz bir integral türü olduğu durumdaS₂?veyaS₂'dır. Özellikle:-
S₁sbyteveS₂byte,ushort,uintveyaulong -
S₁shortveS₂ushortveyauintya daulong -
S₁intveS₂uintveyaulong -
S₁long'dır veS₂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,
Fgenel 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:
-
Fiç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
Ftür parametreleri değiştirildiyse, kısıtlamaları karşılanmıştır. -
Fstatik 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. -
Fbir ö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ü
Ebir değer türündeyseVveMiçindeVbildirilir veya geçersiz kılınırsa:-
Edeğ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 durumdaEbir değişken olarak sınıflandırılır. - Değişken olarak sınıflandırılmamışsa
EVveya salt okunur bir yapı türü değilse (§16.2.2) veMsalt okunur işlev üyesi değilse (§16.4.12) veEşunlardan biridir:- bir giriş parametresi (§15.6.2.3.2) veya
- bir
readonlyalanı (§15.5.3) veya - bir
readonlybaşvuru değişkeni veya dönüş (§9.7), ardından türündekiEgeçici bir yerel değişken oluşturulur ve değeriEbu değişkene atanır.Edaha sonra bu geçici yerel değişkene başvuru olarak yeniden sınıflandırılmış olur. Geçici değişkenethisiçindeMolarak erişilebilir ancak başka bir şekilde erişilemez. Bu nedenle, yalnızcaEyazılabilirse, çağıranınM'ninthisyaptığı 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.Etarafından referans verilen değişken,thistarafından referans verilen değişken olur.
-
- Yoksa:
-
Edeğ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.
-
Etürü bir value_typeise, 'i birE'e dönüştürmek için bir boxing dönüşümü (§10.2.9) yapılır veE, aşağıdaki adımlarda bu class_type olarak kabul edilir. value_type bir enum_typeise, class_typeSystem.Enum;'dur, yoksaSystem.ValueType'dur. -
Edeğeri geçerli olup olmadığı kontrol edilir.Edeğeri null ise, birSystem.NullReferenceExceptionfırlatılır ve başka adım yürütülmez. - Çağrılacak işlev üyesi uygulaması belirlenir:
-
Ebağ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ğlananE'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) uygulanarakEbelirlenir. - Aksi takdirde,
Mbir sanal işlev üyesiyse, çağrılacak işlev üyesi,Mtarafından başvurulan örneğin çalışma zamanı türü tarafından sağlananEuygulamasıdır. Bu işlev üyesi, tarafından başvuruda bulunılan örneğin çalışma zamanı türüne göreMen çok türetilmiş uygulamasını (E) belirleme kuralları uygulanarak belirlenir. - Aksi takdirde,
Msanal olmayan bir işlev üyesidir ve çağıracak işlev üyesiMkendisidir.
-
- Yukarıdaki adımda belirlenen işlev üyesi uygulaması çağrılır.
Etarafından başvurulan nesne, bu nesneye başvurulan nesne olur.
-
Not:§12.2, erişimci veya
geterişimci olmak üzere ilgili işlev üyesinisetç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.ValueTypeveyaSystem.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
- Eğer
E,nöğeleri olan bir tanımlama grubu ifadesiyse, yapısızlaştırmanın sonucuEifadesinin kendisidir. - Aksi takdirde,
E'ın(T1, ..., Tn)öğesi olan bir tanımlama grubu türünvarsa, o zamanE,__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,
Esökülemez.
Burada __v ve __v1, ..., __vn görünmez ve erişilemez geçici değişkenlere başvurur.
Not:
dynamictü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) veSystem.FormattableString(§C.3) belgelerinden belirlenebilir. son notu
hem 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) veSystem.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.IFormattablebelgelerinde (§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'danI'e kadar her sayı0için, eğerN-1ise:- Yer tutucu tanımı
- Sol süslü parantez (
{) karakteri -
Iondalı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
- Sol süslü parantez (
- Interpolated_Regular_String_Mid veya Interpolated_Verbatim_String_Mid karakterleri, eğer varsa, ilgili interpolasyonun hemen ardından gelir.
- Yer tutucu tanımı
- 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
Xbiçim belirtimi, -
stringdeğ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:
-
esı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. -
esıfırsa ve simple_name, genel bir yöntem bildiriminde ama method_declaration'nın öznitelikleri dışında yer alıyorsa ve bu bildirimIadlı 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ü:-
esıfırsa veTbildirimiIadlı bir tür parametresi içeriyorsa, simple_name bu tür parametresine başvurur. - Aksi takdirde, içindeki
I'ninTtür bağımsız değişkenleriyle üye araması (e) eşleşme oluşturursa:-
Themen 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 ifadesithisolan 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ızcaesı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.-
esıfırsa veINiçindeki bir ad alanının adıysa:-
simple_name oluştuğu konum
Niçin bir ad alanı bildirimiyle kapsanıyorsa ve ad alanı bildirimi ad alanı veya türle ilişkilendiren bir extern_alias_directive veyaIiçeriyorsa, simple_name belirsizdir ve derleme zamanı hatası oluşur. - Aksi takdirde, simple_name,
IiçindekiNadlı ad alanına atıfta bulunur.
-
simple_name oluştuğu konum
- Aksi takdirde,
Nerişilebilir bir tür içeriyorsa, ismiIveetür parametrelerine sahipse:-
esıfır ise ve basit_ad oluştuğu yer,Niç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 veyaIiç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:-
esı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şkilendirilenIiç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
Iveetü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
Iveetü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
eItanı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
ailefarası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 inferredson ö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ü öğesiTi 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.NiveyaE?.Niolan bir tanımlama grubu öğesi ifadesine sahiptir veya -
NiItemXbiçimindedir, buradaXbir0ile başlatılmamış ondalık basamak dizisini temsil eder ve bir tanımlama grubu öğesinin konumunu gösterebilir, ancakXöğenin konumunu temsil etmez.
- Tanımlama grubu ifadesinin başka bir öğesi
- 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 typeBu örnekte, tüm dörtlü ifadeler geçerlidir. İlk ikisi,
t1vet2, 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'denlong'ye venull'tenstring'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:
-
esıfır veEbir ad alanıysa veEadıIolan iç içe bir ad alanı içeriyorsa, sonuç bu ad alanıdır. - Aksi takdirde,
Ebir ad alanıysa veE, adıIolan veKtü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. -
Etür olarak sınıflandırılırsa,Ebir tür parametresi değilse veItür parametreleriyleEüye araması (K) eşleşme oluşturursa,E.Ideğ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
Ksı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-
Ibir tür tanımlarsa, sonuç, verilen tür bağımsız değişkenleriyle oluşturulan türdür. -
Ibir veya daha fazla yöntemi tanımlarsa, sonuç ilişkili örnek ifadesi olmayan bir yöntem grubudur. -
Istatik bir özellik tanımlarsa, sonuç ilişkili örnek ifadesi olmayan bir özellik erişimidir. -
Istatik 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çindeEstatik alanın değeridir. - Aksi takdirde sonuç,
IiçindekiEstatik alanı, yani bir değişkendir.
- 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
-
Istatik 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.Itam olarakIstatik bir alan gibi işlenir. - Aksi takdirde, sonuç ilişkili örnek ifadesi olmayan bir olay erişimidir.
- 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,
-
Ibir sabit tanımlarsa, sonuç bir değerdir, yani bu sabitin değeridir. -
Ibir numaralandırma üyesi tanımlarsa, sonuç bir değerdir ve bu da o numaralandırma üyesinin değeridir. - Aksi takdirde,
E.Igeçersiz bir üye başvurusudur ve derleme zamanı hatası oluşur.
-
-
Ebir özellik erişimi, indeksleyici erişimi, değişken veya değerse, türüTve tür bağımsız değişkenleriyleIiçindeTüye araması (K) bir eşleşme sağlıyorsa,E.Iaşağıdaki gibi değerlendirilir ve sınıflandırılır:- İlk olarak,
Ebir ö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. -
Ibir veya daha fazla yöntem tanımlarsa, sonuçEilişkili örnek ifadesi olan bir yöntem grubudur. -
Ibir örnek özelliği tanımlarsa sonuç,Eilişkili örnek ifadesi ve özelliğin türü olan ilişkili bir tür ile özellik erişimidir.Tbir 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. -
Tbir class_type ise veIbu class_typebir örnek alanını tanımlar:-
Edeğerinullise birSystem.NullReferenceExceptionatı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ğeriE. - Aksi takdirde sonuç,
Itarafından referans verilen nesnedekiEalanı olan bir değişkendir.
-
-
Tbir struct_type ise veIbu struct_typebir örnek alanını tanımlar:-
Ebir 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ğindeEalanının değeri olan bir değerdir. - Aksi takdirde sonuç,
Itarafından verilen yapı örneğinde alanEbir değişkendir.
-
-
Ibir ö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.Itam olarakIbir örnek alanıymış gibi işlenir. - Aksi takdirde, sonuç
Eile ilişkili bir örnek ifadesine sahip bir olay erişimidir.
- 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
- İlk olarak,
- Aksi takdirde,
E.Ibir 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.Igeç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,
Asınıfı içinde,Colortürüne başvuranColortanımlayıcısının bu oluşumları«...»ile sınırlandırılır veColoralanı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:
Ptü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.Tboş olamaz bir değer türüyse,EtürüT?olur veEanlamı, şu anlamla aynıdır:((object)P == null) ? (T?)null : P.Value.ASadece
P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.Aksi takdirde
E'ın türüT'dir veE'nin anlamı, şu anlamla aynıdır:((object)P == null) ? (T)null : P.Value.ASadece
P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.
Yoksa:
TP.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.Tboş olamaz bir değer türüyse,EtürüT?olur veEanlamı, şu anlamla aynıdır:((object)P == null) ? (T?)null : P.ASadece
P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.Aksi takdirde
E'ın türüT'dir veE'nin anlamı, şu anlamla aynıdır:((object)P == null) ? (T)null : P.ASadece
P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.
Not: Şu formdaki bir ifade:
P?.A₀?.A₁Eğer
P,nullolarak değerlendirilirse, neA₀ne deA₁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
Ö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;
IsValidtruedöndürürse,p'ninNameö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. Ancakxçalışma zamanındanullise,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,lvise bir çıkış parametresidir ve basit bir atama gerçekleştirir.Yöntem
M,stüründekistringdeğişkeniniAssign'ü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ı
Tsınıf türündeyse, ilişkili tür,Tile 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ı
Tsınıf türündeyse, ilişkili tür,Tile 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öntemMiçin:-
Fgenel değilse,Fşu durumlarda bir adaydır:-
M'nun tür bağımsız değişken listesi yok ve -
FA(§12.6.4.2) ile ilgili olarak geçerlidir.
-
-
Fgenelse veMtür bağımsız değişken listesi yoksa,Faş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,
Fparametre listesinde oluşturulan tüm türler kısıtlamalarını (§8.4.5) karşılar veFparametre listesiA(§12.6.4.2) için geçerlidir
-
Fgenelse veMtür bağımsız değişken listesi içeriyorsa,Faş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,
Fparametre listesinde oluşturulan tüm türler kısıtlamalarını (§8.4.5) karşılar veFparametre listesiA(§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.Fiçin, yöntemC'ninFtüründe bildirildiği durumlarda, temel türCiç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,
objectdışı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 bildirimleriMₑ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öntemleriyleMₑgenel olmayan tür bildirimlerini doğrudan içeriyorsa, bu uzantı yöntemlerinin kümesi aday kümesidir.
- Verilen ad alanı veya derleme birimi, doğrudan uygun uzantı yöntemleri
- 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
nulldeğ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 veCyö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, üzerindeC.Gönceliklidir veE.FhemD.Fhem deC.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,
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:
-
Ddeğerlendirilir. Bu değerlendirme bir istisnaya neden olursa, başka adımlar yürütülmez. - Bağımsız değişken listesi
Adeğerlendirilir. Bu değerlendirme bir istisnaya neden olursa, başka adımlar yürütülmez. -
Ddeğeri geçerli olup olmadığı kontrol edilir.Ddeğerinullise birSystem.NullReferenceExceptionatılır ve başka adım yürütülmez. - Aksi takdirde,
Dbir 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:
Ehiçbir şey olarak sınıflandırılmazsa anlamı bloğunun anlamı ile aynıdır:{ if ((object)P != null) PA; }ancak
Pyalnızca bir kez değerlendirilir.Aksi takdirde
Eanlamı, 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 dynamicson ö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ündelongulong - yalnızca tek dereceli dizi erişimi için, veya türünde
Index; veyaRange - 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:
-
Pdeğ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
intuinttek sıralı dizi erişimi için veyalongörtük dönüştürmenin (ulong) bulunduğu türlerdenIndexRangeilkine 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.
-
Pdeğeri geçerli olup olmadığı kontrol edilir.Pdeğerinullise birSystem.NullReferenceExceptionatılır ve başka adım yürütülmez. - Yukarıdaki adımlar türdeki
Rangetek bir dizin değeri ürettiyse:-
L, tarafından
Pbaşvuruda bulunılan dizinin uzunluğu olsun. -
AL (§18.3) bakımından geçerli olup olmadığını denetler. Aksi takdirde birSystem.ArgumentOutOfRangeExceptionoluş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.
-
L, tarafından
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
Rangedeğ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, birSystem.IndexOutOfRangeExceptionoluş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ündeIndexRange - 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:
-
Pdeğ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 , veyaRangetü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.
-
Pdeğeri geçerli olup olmadığı kontrol edilir.Pdeğerinullise birSystem.NullReferenceExceptionatılır ve başka adım yürütülmez. - Yukarıdaki adımlar türünde
Rangebir dizin değeri üretmişse:- Dize erişimini değerlendirmenin sonucu türündeki
stringbir 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 birSystem.ArgumentOutOfRangeExceptionoluş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
Pkarakterleri kopyalanarak oluşturulan bir dizedir; N sıfır ise dize boştur.
- Dize erişimini değerlendirmenin sonucu türündeki
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
charbir 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, birSystem.IndexOutOfRangeExceptionoluş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
Perişiminin sonucu olur.
- Dize erişimini değerlendirmenin sonucu türündeki
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:
-
Ttarafından sağlanan dizin oluşturucular seti oluşturuldu. Küme,T'da veyaT'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.Iaşağıdaki kurallar uygulanır ve buradaSdizin oluşturucuIbildirildiği türdür:-
IA(§12.6.4.2) ile ilgili olarak geçerli değilseIkümeden kaldırılır. -
I(A) ile ilgili geçerliyse, temelStüründe bildirilen tüm dizin oluşturucular kümeden kaldırılır. -
IA(§12.6.4.2) için geçerliyse veSobjectdışı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_expression
Pdeğerlendirilir. -
argument_list
Adizin ifadeleri soldan sağa doğru sırayla değerlendirilir. - Bağlama zamanında belirlenen en iyi dizin oluşturucuyu kullanma:
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:
Ptürü null atanabilir bir değer türüyse:TP.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.Tboş olamaz bir değer türüyse,EtürüT?olur veEanlamı, şu anlamla aynıdır:((object)P == null) ? (T?)null : P.Value[A]BSadece
P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.Aksi takdirde
E'ın türüT'dir veE'nin anlamı, şu anlamla aynıdır:((object)P == null) ? null : P.Value[A]BSadece
P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.
Yoksa:
TP[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.Tboş olamaz bir değer türüyse,EtürüT?olur veEanlamı, şu anlamla aynıdır:((object)P == null) ? (T?)null : P[A]BSadece
P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.Aksi takdirde
E'ın türüT'dir veE'nin anlamı, şu anlamla aynıdır:((object)P == null) ? null : P[A]BSadece
P'ın yalnızca bir kez değerlendirilmesi bir istisnadır.
Not: Şu formdaki bir ifade:
P?[A₀]?[A₁]Eğer
P,nullolarak değerlendirilirse, neA₀ne deA₁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. -
thisbir 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. -
thisbir 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,
thisdeğ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,
thisdeğişkeni yapı türününrefparametresiyle tam olarak aynı şekilde davranır. Bu, özellikle değişkenin başlangıçta atanmış olarak kabul edildiği anlamına gelir.
- Oluşturucu bildiriminde oluşturucu başlatıcısı yoksa,
-
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)
thisdeğilse, değişken yöntemin veya erişimcinin çağrıldığı yapıyı temsil eder.- Yapı bir
readonly structise,thisdeğişkeni yapı türünün giriş parametresiyle tam olarak aynı şekilde davranır. - Aksi takdirde
thisdeğişkeni, yapı türününrefparametresiyle tam olarak aynı şekilde davranır
- Yapı bir
- Yöntem veya erişimci bir yineleyici veya zaman uyumsuz işlevse,
thisdeğ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.
- Yöntem veya erişimci bir yineleyici (§15.15) veya zaman uyumsuz işlev (§15.14)
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:
thisaksinebasekendi 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:
-
xbir değişken olarak sınıflandırılırsa:-
xdeğişkeni üretmek için değerlendirilir. -
xdeğeri kaydedilir. -
xkaydedilen 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
xtürüne dönüştürülür vexönceki değerlendirmesi tarafından verilen konumda depolanır. -
xdeğ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) vexile ilişkili olan bağımsız değişken listesi (xbir 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. -
xkaydedilen 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
xtürüne dönüştürülür vexkümesi erişimcisi, değer bağımsız değişkeni olarak bu değerle çağrılır. -
xdeğerinin kaydedilen hali, işlemin sonucu olur.
- Örnek ifadesi (
++ ve -- işleçleri ön ek gösterimini de destekler (§12.9.7). 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ü veAmevcut değilse: - Aksi takdirde, eğer
Tbir type_parameter ise veAyoksa:-
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.
-
için değer türü kısıtlaması veya oluşturucu kısıtlaması (
- Aksi takdirde,
Tbir class_type veya struct_typeise:-
Tsoyut 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.
-
Tbir class_typeise:- Sınıf
T'ın yeni bir örneği tahsis edilir. Yeni örneği ayırmak için yeterli bellek yoksa, birSystem.OutOfMemoryExceptionoluş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.
- Sınıf
-
Tbir struct_typeise:-
Ttü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
__agö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,__p1ve__p2gö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,__c1ve__c2gö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;
p1vep2aynı 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 ifadesiint[,]türünde bir dizi örneği oluşturur ve yeniint[10][,]dizi oluşturma ifadesiint[][,]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 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.OverflowExceptionfı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.OutOfMemoryExceptionoluş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ğerinull. Aynı dizi oluşturma ifadesinin alt dizileri de örneklemesi mümkün değildir ve bu ifadeint[][] a = new int[100][5]; // ErrorBu, 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" }; // ErrorNe
intne destringö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ğinobject[]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:
Ebir yöntem grubuysa, temsilci oluşturma ifadesi, 'denE'a bir yöntem grubu dönüştürme (D) ile aynı şekilde işlenir.Eanonim bir işlevse, temsilci oluşturma ifadesi 'danE'a anonim işlev dönüştürmesi (D) ile aynı şekilde işlenir.Bir değerse
E,Eile uyumlu olmalıdır (D) ve sonuç, çağıranEtek 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:
-
Ebir yöntem grubuysa, temsilci oluşturma ifadesi 'denE'a bir yöntem grubu dönüştürmesi (D) olarak değerlendirilir. -
Eanonim bir işlevse, temsilci oluşturma işlemiE'denD'a (§10.7) anonim işlev dönüştürmesi olarak değerlendirilir. -
Ebir delegate_typedeğeriyse:-
Edeğerlendirilir. Bu değerlendirme bir istisnaya neden olursa, başka adımlar yürütülmez. -
Edeğerinullise birSystem.NullReferenceExceptionatı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, birSystem.OutOfMemoryExceptionoluş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.falanı, ikinciSquareyöntemine başvuran bir temsilciyle başlatılır çünkü bu yöntem parametre listesiyle tam olarak eşleşir veDoubleFunctürü döndürür. İkinciSquareyö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
objectile 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.Typenesnesi, dildeki yöntemlere yansımaya izin veren sınıf kitaplıklarında kullanışlıdır; burada bu yöntemler,voidyö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]
intveSystem.Int32aynı türde olduğunu unutmayın. "typeof(X<>)sonucu, tür bağımsız değişkenine bağlı değildir; ancaktypeof(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
floatveyadoubletü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:
-
checkedBir 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 birSystem.OverflowExceptionfırlatılır. -
uncheckedbir 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,
Fyöntemi birSystem.OverflowExceptionfırlatır veGyöntemi aralık dışı sonucun alt 32 bitlik kısmı olan –727379968 değerini döndürür.Hyönteminin davranışı, derleme için varsayılan taşma denetimi bağlamını temel alır, ancakFveyaGile 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 }
FveHsabit ifadeler değerlendirilirken oluşan taşmalar, ifadelercheckedbağlamda değerlendirildiğinden derleme zamanı hatalarının bildirilmesine neden olur.Gsabit ifadesi değerlendirilirken de taşma meydana gelir, ancak değerlendirme biruncheckedbağ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
checkedkullanımı,x * yiçindekiMultiplydeğerlendirilmesini etkilemez, bu nedenlex * yvarsayı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. Sabitlerintaralığının dışında olduğundan,uncheckedişleci olmadanintatamaları derleme zamanı hataları üretir.son örnek
Not:
checkedveuncheckediş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ındanSpan<int>'e dönüştürülen birReadOnlySpan<int>ile sonuçlanır. Benzer şekilde,span9için elde edilenSpan<double>, gösterildiği gibi dönüştürme kullanılarak kullanıcı tanımlı türeWidget<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
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,
nameofad alanında bildirilen genel bir türList<T>varsayılarak çeşitliSystem.Collections.Genericifadelerinin 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 venameof(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) -
dynamicdiğ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ç,
Xsıfırdan çıkarılarak hesaplanır.Xdeğeri işlenen türünün en küçük temsil edilebilir değeriyse (intiçin−2³¹ veyalongiçin −2⁶³ ),Xmatematiksel olumsuzlaması işlenen türü içinde temsil edilemez. Bu bircheckedbağlamında oluşursa, birSystem.OverflowExceptionoluşturulur; biruncheckedbağ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,intdeğ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,longdeğ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ş
Xdeğeridir.xNaNise sonuç daNaN.Ondalık olumsuzlama:
decimal operator –(decimal x);Sonuç,
Xsı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:
-
xbir değişken olarak sınıflandırılırsa:-
xdeğişkeni üretmek için değerlendirilir. -
xdeğ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,xdeğ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) vexile ilişkili olan bağımsız değişken listesi (xbir 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. -
xalma 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.xkümes erişimci, değer argümanı olarak bu değerle çağrılır. - Bu değer aynı zamanda işlemin sonucu olur.
- Örnek ifadesi (
++ 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)–yifadesi, ya 'in–ytürüne çevrilmesi anlamındaki birxya da bir parantezli ifade ile birleştirilmiş bir toplama ifadesi olarak yorumlanabilir (bu dax – 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 veasdışı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:
xveytanımlayıcıysa,x.yaslında bir türü ifade etmese bilex.ytür için doğru dil bilgisidir. son örnek
Not: Kesinleştirme kuralına göre,
xveytanımlayıcıysa,(x)y,(x)(y)ve(x)(-y)cast_expression'dir; ancak,(x)-ybir tür tanımlasa bile,xdeğ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 t ifadesi, aşağıdakilerden biri doğruysa beklenebilir:
-
t, derleme zamanı türüdynamic'dır. -
tparametresiz ve tür parametresi olmayanGetAwaiteradlı erişilebilir bir örnek veya uzantı yöntemi ve aşağıdakilerin tümünün tutıldığı bir dönüş türüAvardır:-
AarabirimSystem.Runtime.CompilerServices.INotifyCompletionuygular (bundan sonra kısaINotifyCompletionolarak bilinir) -
A,IsCompletedtüründe erişilebilir, okunabilir bir örnek özelliğiboolsahiptir -
Aparametresiz ve tür parametresi olmayanGetResulteriş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ğerlendirilerekb(a).IsCompletedelde edilir. -
bfalseise değerlendirme,aarabirimiSystem.Runtime.CompilerServices.ICriticalNotifyCompletionuygulayıp uygulamadığına bağlıdır (bundan sonra kısalık içinICriticalNotifyCompletionolarak 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:-
aICriticalNotifyCompletiongerçekleştirmezse((a) as INotifyCompletion).OnCompleted(r)ifadesi değerlendirilir. -
aICriticalNotifyCompletionuygularsa,((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:
-
xvarsa sol işlenendir; aksi takdirde ifade0; ve -
yvarsa 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);checkedbağlamında, ürün sonuç türü kapsamında değilse, birSystem.OverflowExceptionatılır.uncheckedbağ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,
xveypozitif 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,zsonsuzdur. Yuvarlama nedeniyle,zveyaxsıfır olmasa bileysıfır olabilir.+y-y+0-0+∞-∞NaN+x+z-z+0-0+∞-∞NaN-x-z+z-0+0-∞+∞NaN+0+0-0+0-0NaNNaNNaN-0-0+0-0+0NaNNaNNaN+∞+∞-∞NaNNaN+∞-∞NaN-∞-∞+∞NaNNaN-∞+∞NaNNaNNaNNaNNaNNaNNaNNaNNaN(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.OverflowExceptionhatası 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.DivideByZeroExceptionfı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
intveyalongdeğeriyse ve sağ işlenen–1ise, taşma meydana gelir.checkedbağlamında, bu birSystem.ArithmeticException(veya alt sınıfının) atılmasına neden olur.uncheckedbir bağlamda, birSystem.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,
xveypozitif sonlu değerlerdir.z, en yakın temsil edilebilir değere yuvarlanmışx / ysonucudur.+y-y+0-0+∞-∞NaN+x+z-z+∞-∞+0-0NaN-x-z+z-∞+∞-0+0NaN+0+0-0NaNNaN+0-0NaN-0-0+0NaNNaN-0+0NaN+∞+∞-∞+∞-∞NaNNaNNaN-∞-∞+∞-∞+∞NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNOndalık bölme:
decimal operator /(decimal x, decimal y);Eğer sağ işlenenin değeri sıfırsa, bir
System.DivideByZeroExceptionfırlatılır. Elde edilen değerin büyüklüğü ondalık biçimde gösteremeyecek kadar büyükse, birSystem.OverflowExceptionhatası 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 % ysonucu,x – (x / y) * ytarafından üretilen değerdir.ysıfırsa, birSystem.DivideByZeroExceptionfırlatılır.Sol işlenen en küçük
intveyalongdeğerse ve sağ işlenen–1ise, ancak ve ancakSystem.OverflowExceptionbir istisna oluşturuyorsa birx / yoluş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,
xveypozitif sonlu değerlerdir.z,x % ysonucudur vex – 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+zNaNNaN+x+xNaN-x-z-zNaNNaN-x-xNaN+0+0+0NaNNaN+0+0NaN-0-0-0NaNNaN-0-0NaN+∞NaNNaNNaNNaNNaNNaNNaN-∞NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNOndalık kalan:
decimal operator %(decimal x, decimal y);Eğer sağ işlenenin değeri sıfırsa, bir
System.DivideByZeroExceptionfı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 durumdax / yiç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şaretixile 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);checkedbağlamında, toplam sonuç türü aralığının dışındaysa, birSystem.OverflowExceptionatılır.uncheckedbağ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,
xveysıfır olmayan sonlu değerlerdir vezx + ysonucudur.xveyaynı büyüklüğe ancak karşıt işaretlere sahipse,zpozitif sıfırdır.x + yhedef türünde temsil edilemeyecek kadar büyükse,zx + yile aynı işareti olan bir sonsuzdur.y+0-0+∞-∞NaNxzxx+∞-∞NaN+0y+0+0+∞–∞NaN-0y+0-0+∞-∞NaN+∞+∞+∞+∞+∞NaNNaN-∞-∞-∞-∞NaN-∞NaNNaNNaNNaNNaNNaNNaNNaNOndalı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.OverflowExceptionhatası 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
Enumaralandırma türü veUiseE'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şleneninullise, yerine boş bir dize geçirilir. Aksi takdirde, herhangi birstringolmayan işlenen,ToStringtüründen devralınan sanalobjectyöntemi çağrılarak string gösterimine dönüştürülür.ToStringnulldö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
ToStringyö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 zamannulldeğeri döndürmez. Sonuç dizeyi oluşturmak için yeterli bellek yoksa birSystem.OutOfMemoryExceptionhatası meydana gelebilir.Temsilci birleşimi. Her temsilci türü,
Dtemsilci 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ı zamandanullolsa bile). Aksi takdirde, ikinci işlenennullise, 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.Delegatebir 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 ycheckedbağlamında, fark sonuç türü aralığının dışındaysa, birSystem.OverflowExceptionatılır.uncheckedbağ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,
xveysıfır olmayan sonlu değerlerdir vezx – ysonucudur.xveyeşitse,zpozitif sıfır olur.x – yhedef türünde temsil edilemeyecek kadar büyükse,zx – yile aynı işareti olan bir sonsuzdur.y+0-0+∞-∞NaNxzxx-∞+∞NaN+0-y+0+0-∞+∞NaN-0-y-0+0-∞+∞NaN+∞+∞+∞+∞NaN+∞NaN-∞-∞-∞-∞-∞NaNNaNNaNNaNNaNNaNNaNNaNNaN(Yukarıdaki tabloda,
-ygirdileri 'ünyanlamı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.OverflowExceptionhatası 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ü,
Esabit listesi türü veUE'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çxveysı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ü,
Dtemsilci 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 sonucunullolur. - 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.
- Listeler, temsilci eşitlik işleci (§12.14.9) tarafından belirlenen eşitliği karşılaştırırsa, işlemin sonucu olur
İş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
- İlk operand
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ı kadarx'i sola kaydırır.xsonuç 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ı kadarx'i sağa kaydırır.xintveyalongtüründe olduğunda, düşük sıralıxbitleri atılır, kalan bitler sağa kaydırılır vexnegatif değilse yüksek sıralı boş bit konumları sıfıra ayarlanır vexnegatifse bir olarak ayarlanır.xuintveyaulongtüründe olduğunda, düşük sıralıxbitleri 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:
-
xtürüintveyauintolduğunda, vardiya sayısı düşük sıralı beş bitcounttarafından verilir. Başka bir deyişle, vardiya sayısıcount & 0x1F'dan hesaplanır. -
xtürülongveyaulongolduğunda, vardiya sayısı alt sıralı altı bitcounttarafı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şlemunchecked ((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 kapsayanifadesi 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_expressionbirisiç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.
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:
xveybiri NaN isex < 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 iseTbir değer türü olduğu bilinmeyen ve değer türü kısıtlamasına sahip olmayan birTolduğu türünde bir değerdir.- Çalışma zamanında
Tnull atanamaz bir değer türüyse,=='in sonucufalseve!='ün sonucutrueolur. - Çalışma zamanında
Tnull 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
Tbir referans tipi ise, operandtrueise sonuçnullve aksi takdirdefalse.
- Çalışma zamanında
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 == yya dax != yşeklinde olan bir işlemi için, geçerli kullanıcı tanımlıoperator ==veyaoperator !=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 == nullnull atanamayan bir değer türünü temsil edebilse deTyapısına izin verilir ve sonuç,falsenull atanamayan bir değer türü olduğundaTolarak 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
svetdeğişkenleri aynı karakterleri içeren iki ayrı dize örneğine başvurur. her iki işlenen de türündeTrueolduğunda önceden tanımlanmış dize eşitliği işleci (§12.14.8) seçildiğinden ilk karşılaştırma çıktısıstringolur. Geriye kalan tüm karşılaştırmalar, işlenenlerden herhangi birinin bağlama zamanı türüFalseolduğundaoperator ==türündekistringaşırı yüklemesi geçerli olmadığından,objectsonucunu 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ışintdeğ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 örneklerine
nullolmayan 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 denullise 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ı nedeniyle
nullolmayan 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
xdeğerlendirilir. - Sağ taraftaki operand
ydeğerlendirilir. - Sözcük sırasına göre
xiveyiiçeren her bir öğe çifti için:- İşleç
xi == yideğerlendirilir vebooltürünün sonucu aşağıdaki şekilde elde edilir:- Karşılaştırma bir
boolverdiyse sonuç bu olur. - Aksi takdirde, karşılaştırma bir
dynamicverdiyse,falseişleci dinamik olarak çağrılır ve sonuçta elde edilenbooldeğ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 edilenbooldeğeri mantıksal olumsuzlama işleci (!) ile tersine çevrilir.
- Karşılaştırma bir
- Elde edilen
boolfalseise, başka bir değerlendirme gerçekleşmez ve demet eşitlik işlecinin sonucufalseolur.
- İşleç
- Tüm öğe karşılaştırmaları
trueverdiyse, demet eşitlik operatörünün sonucutrueolur.
Tüple eşitlik işleci x != y aşağıdaki şekilde değerlendirilir:
- Sol taraftaki operand
xdeğerlendirilir. - Sağ taraftaki operand
ydeğerlendirilir. - Sözcük sırasına göre
xiveyiiçeren her bir öğe çifti için:- İşleç
xi != yideğerlendirilir vebooltürünün sonucu aşağıdaki şekilde elde edilir:- Karşılaştırma bir
boolverdiyse sonuç bu olur. - Aksi takdirde, karşılaştırma bir
dynamicverdiyse,trueişleci dinamik şekilde çağrılır ve elde edilenbooldeğ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 edilenbooldeğeri sonuç olur.
- Karşılaştırma bir
- Elde edilen
booltrueise, başka bir değerlendirme gerçekleşmez ve demet eşitlik işlecinin sonucutrueolur.
- İşleç
- Tüm öğe karşılaştırmaları
falseverdiyse, demet eşitlik operatörünün sonucufalseolur.
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:
-
Eanonim bir işlev veya yöntem grubuysa, derleme zamanı hatası oluşur. - Boş değer atanabilir bir başvuru türüyse
T(§8.9.3), derleme zamanı hatası oluşur. - Eğer
Enullsabit ise veyaE'nin değerinullise, sonuçfalseolur. - Yoksa:
-
R'in çalışma zamanı türüEolsun. - Şu
Dşekilde türetilebilirR:-
Rnull atanabilir bir değer türüyse,D'nin temel türüR'dir. - Aksi takdirde,
DRolur.
-
- Sonuç aşağıdakine bağlıdır
DT:-
Tbir başvuru türüyse, sonuç şu durumdatrueolur:- ve
DarasındaTbir kimlik dönüştürmesi var veya -
Dbir referans türüdür veD'denT'ye örtük bir referans dönüştürmesi vardır veya -
Dbir değer türüdür ve bir kutulama dönüştürmesiDTvardır.
- ve
- Eğer
Tnull atanabilir bir değer türüyse vetrue'ün temel alınan türüDise, sonuçTolur. - Eğer
Tnull atanamaz bir değer türüyse vetrueileDaynı türdeyse, sonuçTolur. - Aksi takdirde sonuç
false.
-
-
Kullanıcı tanımlı dönüştürmeler is işleci tarafından dikkate alınmaz.
Not:
isiş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:
isişleci, derleme zamanı türleri ve dönüştürmeleri açısından aşağıdaki gibi anlaşılabilir ve buradaCEderleme zamanı türüdür:
ederleme 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:
Cnull değer türünde değilse, işlemin sonucutrueolur.- 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ürseCT(§8.4.3) varsa, yukarıdaki çalışma zamanı denetimleri yapılır.- Aksi takdirde,
EtüründenTtürüne bağlantı, kutulama, sarmalama veya kutu açma dönüşümü mümkün değildir ve işlemin sonucufalseolur. 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.
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'denT'e var. -
EveyaTtürü açık bir türdür. -
E,nullsabit 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'inGtü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 olsunHdeğildir; bu nedenleas'teHiş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, ancakyyalnızcaxfalsedeğilse değerlendirilir. - İşlem
x || yx | yişlemine karşılık gelir, ancakyyalnızcaxtruedeğ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'ınfalseveoperator false'ninfalsedö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 vebooltürüne dönüştürülür. Ardından,xtrueise,ydeğerlendirilir vebooltürüne dönüştürülür ve bu işlemin sonucu olur. Aksi halde, işlemin sonucufalseolur. - İşlem
x || yx ? true : yolarak değerlendirilir. Başka bir deyişle,xönce değerlendirilir vebooltürüne dönüştürülür. Ardından,xtrueise işlemin sonucutrueolur. Aksi takdirde,ydeğerlendirilir vebooltü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 veTtüründen bir sonuç döndürür. -
T,operator truebildirimlerini veoperator 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; buradaT.false(x),operator falseiçinde bildirilenT'ün bir çağrısıdır veT.&(x, y), seçilioperator &'nın bir çağrısıdır. Başka bir deyişle,xönce değerlendirilir veoperator falsekesinlikle yanlış olup olmadığını belirlemek için sonuç üzerindexçağrılır. Ardından,xkesinlikle false ise, işlemin sonucu daha öncexiçin hesaplanan değerdir. Aksi takdirde,ydeğerlendirilir ve seçilenoperator &daha öncexiçin hesaplanan değerde ve işlemin sonucunu üretmek üzereyiçin hesaplanan değerde çağrılır. - İşlem
x || y,T.true(x) ? x : T.|(x, y)olarak değerlendirilir; buradaT.true(x),operator trueiçinde bildirilenT'ün bir çağrısıdır veT.|(x, y), seçilioperator |'nın bir çağrısıdır. Başka bir deyişle,xönce değerlendirilir veoperator truekesinlikle doğru olup olmadığını belirlemek için sonuç üzerindexçağrılır. Ardından,xkesinlikle doğruysa, işlemin sonucu daha öncexiçin hesaplanan değerdir. Aksi takdirde,ydeğerlendirilir ve seçilenoperator |daha öncexiçin hesaplanan değerde ve işlemin sonucunu üretmek üzereyiç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 ?? cifadesia ?? (b ?? c)olarak değerlendirilir. Genel olarak,E1 ?? E2 ?? ... ?? ENşeklindeki bir ifade,nullolmayan işleçlerin ilkini veya tüm işleçlernullisenulldö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:
-
AVarsa 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,
Avarsa vebdinamik bir ifadeyse, sonuç türüdynamicolur. Çalışma zamanında ilk olarakadeğerlendirilir.anulldeğilse,adynamicdönüştürülür ve sonuç olur. Aksi takdirde,bdeğerlendirilir ve sonuç olarak kabul edilir. - Aksi takdirde,
Avarsa ve null atanabilir bir değer türüyse veb'denA₀'a örtük bir dönüştürme varsa, sonuç türüA₀olur. Çalışma zamanında ilk olarakadeğerlendirilir.anulldeğilse,aA₀türüne göre açık hale getirilir ve sonuç bu olur. Aksi takdirde,bdeğerlendirilir veA₀türüne dönüştürülür ve sonuç haline gelir. - Aksi takdirde,
Avarsa veb'danA'a örtük bir dönüştürme varsa, sonuç türüAolur. Çalışma zamanında ilk olarakadeğerlendirilir.anulldeğilse, sonuçaolur. Aksi takdirde,bdeğerlendirilir veAtürüne dönüştürülür ve sonuç haline gelir. - Aksi takdirde,
Avarsa ve null atanabilir bir değer türündeyse,btürüBolduğunda veA₀'tenB'e örtük bir dönüşüm varsa, sonuç türüB'tir. Çalışma zamanında ilk olarakadeğerlendirilir.anulldeğilse,aA₀türüne açılır veBtürüne dönüştürülür, sonuç bu olur. Aksi takdirde,bdeğerlendirilir ve sonuç olarak kabul edilir. - Aksi takdirde,
bbir türBvarsa vea'denB'e örtük bir dönüştürme varsa, sonuç türüBolur. Çalışma zamanında ilk olarakadeğerlendirilir.anulldeğilse,aBtürüne dönüştürülür ve sonuç olur. Aksi takdirde,bdeğerlendirilir ve sonuç olarak kabul edilir. - Aksi takdirde,
avebuyumsuz 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
Ttür parametresiMkısıtlanmamış. Bu nedenle tür bağımsız değişkeni, ilk çağrısındaMgö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ındaMgö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, ifadenina ?? bdeğeri şeklindedira.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 _);
s1bildirimi 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. SonrakiWriteLine, çevreleyen kapsama ekleneni1veb1'ye erişebilir.
s2bildirimi,i2'ün bildirildiği bağımsız değişken listesinde yer aldığı için,M'nin iç içe çağrısındai2'i kullanma girişiminin yasak olduğunu gösterir. Öte yandan son argümandab2referansına izin verilir, çünkü iç içe argüman listesinin sonundab2'in bildirildiği yerden sonra gerçekleşir.
s3bildirimi, 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 : eifadesia ? 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ıdynamictercih 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:
refolduğunda, conditional_expression bir değişken referansı döndürür, bu referans= refiş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.
-
xtürüXveytürüYise,- ile arasında
Xbir kimlik dönüştürmesi varsa, sonuç bir ifade kümesinin en iyi ortak türüdür (Y). Türlerden biridynamicise tür çıkarımıdynamictercih 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, ancakY'danX'a kadar değilse, koşullu ifadenin türüYolur. - Aksi takdirde, 'dan
X'a örtük bir numaralandırma dönüştürmesi (Y) varsa, koşullu ifadenin türüYolur. - Aksi takdirde, 'dan
Y'a örtük bir numaralandırma dönüştürmesi (X) varsa, koşullu ifadenin türüXolur. - Aksi takdirde, 'den
Y'a örtük dönüştürme (X) varsa, ancakX'danY'a kadar değilse, koşullu ifadenin türüXolur. - Aksi takdirde, hiçbir ifade türü belirlenemez ve derleme zamanı hatası oluşur.
- ile arasında
-
xveyyalnızca birinin türü varsa ve hemxhem deybu 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,
bdeğerlendirilir vebool'ninbdeğeri belirlenir:-
btüründenbool'e örtük bir dönüştürme varsa, bu örtük dönüştürmeboolbir değer üretmek için gerçekleştirilir. - Aksi takdirde,
operator truetürü tarafından tanımlananb, birbooldeğeri üretmek için çağrılır.
-
- Yukarıdaki adım tarafından üretilen
booldeğeritrueisexdeğerlendirilir ve sonuçta elde edilen değişken başvurusu koşullu ifadenin sonucu olur. - Aksi takdirde,
ydeğ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,
bdeğerlendirilir vebool'ninbdeğeri belirlenir:-
btüründenbool'e örtük bir dönüştürme varsa, bu örtük dönüştürmeboolbir değer üretmek için gerçekleştirilir. - Aksi takdirde,
operator truetürü tarafından tanımlananb, birbooldeğeri üretmek için çağrılır.
-
- Yukarıdaki adım tarafından üretilen
booldeğeritrueise,xdeğerlendirilir ve koşullu ifadenin türüne dönüştürülür ve bu koşullu ifadenin sonucu olur. - Aksi takdirde,
ydeğ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,Mgibi söz dizimli bir form hata olursa (void). Ancak bir null_conditional_invocation_expressionolarak kabul edildiğinde, sonuç türünevoidizin 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 omittedson ö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 structtüründe bir parametreye erişmesi, derleme zamanı hatasına neden olur. -
thistürü bir yapı türü olduğunda, gövdethis'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ğuxolduğ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
gotodeyimi, birbreakdeyimi veya bircontinuedeyimi içeriyorsa, bu derleme zamanı hatasıdır. - Gövdedeki
returndeyimi, 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 ikiSumyöntemi vardır. Her biri birselectorbağı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 birintveyadoubleolabilir ve sonuçta elde edilen toplam aynı şekilde birintveyadoubleolur.örneğin
Sumyö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şlevSumhemd => d.UnitCounthem deFunc<Detail,int>ile uyumlu olduğundan her ikiFunc<Detail,double>yöntemi de uygulanabilir. Ancak,SumdönüştürmeFunc<Detail,int>dönüştürmeden daha iyi olduğundan, aşırı yükleme çözümlemesi ilkFunc<Detail,double>yöntemini seçer.
orderDetails.Sumikinci çağrıda, anonim işlevSumd => d.UnitPrice * d.UnitCounttüründe bir değer ürettiğinden yalnızca ikincidoubleyöntemi uygulanabilir. Bu nedenle, aşırı yükleme çözümlemesi bu çağrı için ikinciSumyö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
Ö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
xanonim işlev tarafından yakalanır vexömrü en azındanFdö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 3son ö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,
xyerel 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,
xbildiriminin 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 5Ancak,
xbildirimi 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 5Bir 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 3son ö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,
Folarak değiştirilirsestatic 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 ancakyörneklerini ayırır ve çıkış şöyle olur:1 1 2 1 3 1son ö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 10son ö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 " ""
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 colarak çevrilir
from c in (customers).Cast<Customer>() where c.City == "London" select cson çevirisi
customers. Cast<Customer>(). Where(c => c.City == "London")son örnek
Not: Açık aralık değişken türleri, genel olmayan
IEnumerablearabirimini uygulayan koleksiyonları sorgulamak için yararlıdır, ancak genelIEnumerable<T>arabirimini kullanmaz. Yukarıdaki örnekte, müşterilerArrayListtü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 colarak ç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 olmakSelectve 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
xvey'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 oson ç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 cbasitç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.Countryolarak ç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
xvey'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>ileO<T>arasındaki önerilen ilişki,ThenByveThenByDescendingyöntemlerinin yalnızca birOrderByveyaOrderByDescendingsonucunda kullanılabilir olmasını sağlar. son notu
Not: her iç sıranın ek bir
GroupByözelliğine sahip olduğu dizi dizisi olanKeysonucunun ö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.Linqad 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.
İş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ğerinullise 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 = cifadesia = (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ıca
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.
-
xbir demet ifadesiyse, ve(x1, ..., xn)yöğeleriyle ((y1, ..., yn)) bir demet ifadesi olarak deşifre edilebiliyorsa, ven'nın 'e yapılan her atamasıxitürüne sahipse, bu atamayitürüne sahiptir. - Aksi takdirde,
xbir değişken olarak sınıflandırılırsa, değişkenireadonlydeğildirxTtürüne sahiptir veyT'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 vey, türüTolan bir değişkense, değişkenin çıkarılmış türüTve atamaTtürüne sahiptir. - Aksi takdirde,
xbir ö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 vey'ünT'e örtük bir dönüşümü varsa, atamaTtü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,
xdeğerlendirilir. -
xdeğişken olarak sınıflandırılırsa,ydeğerlendirilir ve gerekirse örtük dönüştürme yoluylaTdönüştürülür (§10.2).-
xtarafından verilen değişken bir reference_typedizi öğesiyse,yiçin hesaplanan değerinxöğe olduğu dizi örneğiyle uyumlu olduğundan emin olmak için bir çalışma zamanı denetimi gerçekleştirilir.ynullise 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, birSystem.ArrayTypeMismatchExceptionfırlatılır. -
ydeğ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:-
ydeğerlendirilir ve gerekirse örtük dönüştürme yoluylaTdönüştürülür (§10.2). -
xset 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. -
ydeğerlendirmesi ve dönüşümünden elde edilen değer, atamanın sonucu olarak elde edilir.
-
-
x,(x1, ..., xn)arity'sine sahip bir demetnolarak sınıflandırılırsa:-
y,nöğeleriyleeadlı bir demet ifadesi olarak parçalanmıştır. - örtük bir demet dönüştürmesi kullanılarak
t'ine'ye dönüştürülmesi ile bir sonuç demetiToluşturulur. - Soldan sağa doğru her
xiiçin,xiyeniden değerlendirilmediğinden,t.Itemixi'e atanır. - Atamanın sonucu olarak
telde edilir.
-
Not: Eğer
x'nin derleme zamanı türüdynamicise vey'ün derleme zamanı türündendynamic'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[]'danB[]'ye örtük bir başvuru dönüştürmesinin mevcut olması koşuluyla,Bdizi türündeki bir değerinAdizi 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. Örnektestring[] sa = new string[10]; object[] oa = sa; oa[0] = null; // OK oa[1] = "Hello"; // OK oa[2] = new ArrayList(); // ArrayTypeMismatchExceptionson atama, bir
System.ArrayTypeMismatchExceptionbaşvurusunun birArrayListöğesinde depolanamaması nedeniyle birstring[]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.Xvep.Ydeğişken olduğundan,r.A,r.B,pveratamalarına izin verilir. Ancak örnekteRectangle r = new Rectangle(); r.A.X = 10; r.A.Y = 10; r.B.X = 100; r.B.Y = 100;
r.Aver.Bdeğ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:
= refişlecini kullanarak kod okurken, işlenenin parçası olarakrefbö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= refve sağ operand olarakb ? ref x : ref yşeklinde okumak önemlidir:ref int a = ref (b ? ref x : ref y);. Daha da önemlisi,ref bifadesi 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» ysadece bir kez değerlendirilmesi hariç, işlemxolarak 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
xtürüne dönüştürülebilirse veyxtürüne örtük olarak dönüştürülebilirse veya işleç bir shift işleciyse, işlemx = (T)(x «op» y)olarak değerlendirilir; buradaTxtürüdür. ancakxyalnı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 veBveCintdö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
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; // OKher 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» yveyax = (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 (
nullsabiti 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.
-
checkedveuncheckedifadeleri. -
nameofifadeleri. - Ö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ürensizeofiç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ğı
nulldeğerini değerlendiren sabit bir ifade olduğu sürece mümkündür.
Not:
nullolmayan 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ı,nullolmayan 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)
-
caseetiketleriswitchifadesi (§13.8.3). -
goto caseifadeler (§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 tekilEçö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.
ECMA C# draft specification