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.
13.1 Genel
C# çeşitli ifadeler sağlar.
Not: Bu ifadelerin çoğu C ve C++ ile programlanmış geliştiricilere tanıdık gelecek. dipnot
statement
: labeled_statement
| declaration_statement
| embedded_statement
;
embedded_statement
: block
| empty_statement
| expression_statement
| selection_statement
| iteration_statement
| jump_statement
| try_statement
| checked_statement
| unchecked_statement
| lock_statement
| using_statement
| yield_statement
| unsafe_statement // unsafe code support
| fixed_statement // unsafe code support
;
unsafe_statement (§24.2) ve fixed_statement (§24.7) yalnızca güvenli olmayan kodda (§24) kullanılabilir.
embedded_statement non-terminal'ı, diğer deyimler içinde yer alan deyimler için kullanılır. embedded_statement yerine statement kullanımı, bu bağlamlarda bildirim ifadeleri ve etiketli ifadelerin kullanımını dışlar.
Örnek: Kod
void F(bool b) { if (b) int i = 44; }Bir
ififadesi, dalında bir ifade yerine birifgerektirdiğinden derleme zamanı hatasına sonuçlanır. Bu koda izin verilseydi değişkeniibildirilir, ancak hiçbir zaman kullanılamaz. Ancak,i'nın bildirimini bir blok içine yerleştirerek örneğin geçerli olduğunu unutmayın.son örnek
13.2 Uç noktaları ve ulaşılabilirlik
Her deyimin bir bitiş noktası vardır. Sezgisel anlamda, deyimin bitiş noktası deyiminin hemen ardından gelen konumdur. Bileşik deyimler için yürütme kuralları (katıştırılmış deyimler içeren deyimler), denetim katıştırılmış deyimin bitiş noktasına ulaştığında gerçekleştirilen eylemi belirtir.
Örnek: Denetim bir bloktaki deyimin bitiş noktasına ulaştığında, denetim bloktaki bir sonraki deyime aktarılır. son örnek
Bir deyime yürütme yoluyla ulaşılabiliyorsa, deyimine ulaşılabilir olduğu söylenir. Buna karşılık, bir deyimin yürütülme olasılığı yoksa, deyimin ulaşılamaz olduğu söylenir.
Örnek: Aşağıdaki kodda
void F() { Console.WriteLine("reachable"); goto Label; Console.WriteLine("unreachable"); Label: Console.WriteLine("reachable"); }Console.WriteLine'ın ikinci çağrısına ulaşılamıyor çünkü deyimin yürütülme olasılığı yok.
son örnek
throw_statement, block veya empty_statement dışındaki bir deyime ulaşılamıyorsa bir uyarı bildirilir. Bir ifadenin erişilemez olması özellikle bir hata değildir.
Not: Belirli bir deyimin veya bitiş noktasının ulaşılabilir olup olmadığını belirlemek için, derleyici her deyim için tanımlanan ulaşılabilirlik kurallarına göre akış analizi gerçekleştirir. Akış analizi, deyimlerin davranışını denetleyen sabit ifadelerin (§12.25) değerlerini dikkate alır, ancak sabit olmayan ifadelerin olası değerleri dikkate alınmaz. Başka bir deyişle, denetim akışı analizi amacıyla, belirli bir türe ait sabit olmayan bir ifadenin bu türdeki herhangi bir olası değere sahip olduğu kabul edilir.
Örnekte
void F() { const int i = 1; if (i == 2) Console.WriteLine("unreachable"); }
ififadesinin Boole ifadesi sabit bir ifadedir çünkü==işlecin her iki işleneni de sabittir. Sabit ifade derleme zamanında değerlendirildiğinden,falsedeğeri üretilir veConsole.WriteLineçağrısının ulaşılamaz olduğu kabul edilir. Ancak, yerel değişken olarak değiştirilirseivoid F() { int i = 1; if (i == 2) Console.WriteLine("reachable"); }
Console.WriteLineçağrının ulaşılabilir olduğu kabul edilir, ancak gerçekte hiçbir zaman yürütülmeyecektir.dipnot
bir işlev üyesinin veya anonim bir işlevin bloğu her zaman ulaşılabilir olarak kabul edilir. Bloktaki her deyimin ulaşılabilirlik kuralları ardışık olarak değerlendirilerek, belirli bir deyimin erişilebilirliği belirlenebilir.
Örnek: Aşağıdaki kodda
void F(int x) { Console.WriteLine("start"); if (x < 0) Console.WriteLine("negative"); }ikinci
Console.WriteLineulaşılabilirliği aşağıdaki gibi belirlenir:
- Yöntemin bloğu ulaşılabilir olduğundan ilk
Console.WriteLineifade deyimineFulaşılabilir (§13.3).- İlk
Console.WriteLineifade deyiminin bitiş noktasına ulaşılabilir çünkü bu deyime ulaşılabilir (§13.7 ve §13.3).ifdeyimine ulaşılabilir çünkü ilkConsole.WriteLineifade deyiminin bitiş noktasına ulaşılabilir (§13.7 ve §13.3).- İkinci
Console.WriteLineifade deyimi,ifdeyiminin Boole ifadesi sabit bir değerfalseiçermediğinden ulaşılabilir.son örnek
Deyimin bitiş noktasının ulaşılabilir olması için derleme zamanı hatasının olduğu iki durum vardır:
switchdeyimi bir switch bölümünün sonraki switch bölümüne "geçmesine" izin vermediğinden, switch bölümünün deyim listesinin bitiş noktasına ulaşılması derleme zamanı hatasıdır. Bu hata oluşursa, genellikle birbreakdeyiminin eksik olduğunu gösterir.Bu, bir işlev üyesinin bloğunun bitiş noktası veya bir değeri ulaşılabilir olacak şekilde hesaplayan anonim bir işlev için derleme zamanı hatasıdır. Bu hata oluşursa, genellikle bir
returndeyiminin eksik olduğunun bir göstergesidir (§13.10.5).
13.3 Bloklar
13.3.1 Genel
Blok, birden çok deyimin tek bir deyime izin verilen bağlamlarda yazılmasına izin verir.
block
: '{' statement_list? '}'
;
Bir blok, küme ayraçları içine alınmış opsiyonel bir statement_list (§13.3.2) oluşur. İfadeler listesi atlanırsa, bloğun boş olduğu söylenir.
Blok bildirim deyimleri barındırabilir (§13.6). Yerel değişkenin veya bir blokta bildirilen sabitin kapsamı bloğudur.
Bir blok aşağıdaki gibi yürütülür:
- Blok boşsa, denetim bloğun bitiş noktasına aktarılır.
- Blok boş değilse, denetim deyim listesine aktarılır. Denetim, deyim listesinin bitiş noktasına ulaştığında ve eğer ulaşırsa, denetim bloğun bitiş noktasına aktarılır.
Bloğun kendisi ulaşılabilir ise, o bloğun deyim listesi de ulaşılabilir.
Blok boşsa veya deyim listesinin bitiş noktasına ulaşılabilirse bloğun bitiş noktasına ulaşılabilir.
Bir veya daha fazla deyim içeren bir yield (§13.15) yineleyici bloğu olarak adlandırılır. Yineleyici blokları, işlev üyelerini yineleyici olarak uygulamak için kullanılır (§15.15). Yineleyici blokları için bazı ek kısıtlamalar geçerlidir:
- Bir
returndeyiminin yineleyici bir blokta görünmesi bir derleme zamanı hatasıdır (ancakyield returndeyimlerine izin verilir). - Yineleyici bloğunun güvenli olmayan bir bağlam (§24.2) içermesi derleme zamanı hatasıdır. Yineleyici bloğu, bildirimi güvenli olmayan bir bağlamda iç içe yerleştirilmiş olsa bile her zaman güvenli bir bağlam tanımlar.
13.3.2 İfade listeleri
İfade listesi, sırayla yazılmış bir veya daha fazla ifadeden oluşur. Deyim listeleri s bloğunda(§13.3) ve switch_block'lerde(§13.8.3) yer alır.
statement_list
: statement+
;
Bir ifade listesi, denetimi ilk ifadeye aktararak yürütülür. Denetim bir deyimin bitiş noktasına ulaştığında ve olduğunda, denetim bir sonraki deyime aktarılır. Eğer ve ne zaman kontrol son deyimin bitiş noktasına ulaşırsa, kontrol deyim listesinin bitiş noktasına aktarılır.
Aşağıdakilerden en az biri doğruysa, deyim listesindeki bir deyime ulaşılabilir:
- İfade, ilk ifadedir ve ifadenin listesinin kendisine ulaşılabilir.
- Önceki ifadenin bitiş noktasına ulaşılabilir.
- Deyim, etiketli bir deyimdir ve etikete erişilebilir bir deyim tarafından referans verilir
goto.
Listedeki son deyimin bitiş noktasına ulaşılabilirse, deyim listesinin bitiş noktasına ulaşılabilir.
13.4 Boş deyim
bir empty_statement hiçbir şey yapmaz.
empty_statement
: ';'
;
Boş bir deyim, deyiminin gerekli olduğu bir bağlamda gerçekleştirilecek işlem olmadığında kullanılır.
Boş bir deyimin yürütülmesi yalnızca kontrolü deyimin bitiş noktasına aktarır. Bu nedenle, boş bir deyimin bitiş noktasına, boş deyim erişilebilir olduğunda ulaşılabilir.
Örnek: Boş gövdeli bir
whiledeyim yazarken boş bir deyim kullanılabilir:bool ProcessMessage() {...} void ProcessMessages() { while (ProcessMessage()) ; }Ayrıca, bir bloğun "
}" kapatılmasından hemen önce bir etiket bildirmek için boş bir deyim kullanılabilir:void F(bool done) { ... if (done) { goto exit; } ... exit: ; }son örnek
13.5 Etiketli deyimler
Etiketli bir deyim, bir deyimin başına bir etiket eklenmesine izin verir. Etiketli deyimlere bloklar halinde izin verilir, ancak ekli deyimler olarak izin verilmez.
labeled_statement
: identifier ':' statement
;
Etiketlenmiş bir ifade, tanımlayıcı isim olarak bir etiket bildirir. Bir etiketin kapsamı, iç içe yerleştirilmiş bloklar da dahil olmak üzere etiketin bildirildiği bloğun tamamıdır. Aynı ada sahip iki etiketin çakışan kapsamlara sahip olması derleme zamanı hatasıdır.
Etiketin kapsamındaki deyimlerden goto etiketi (§13.10.4) referans olarak kullanılabilir.
Not: Bu, ifadelerin
gotoblokların içinde ve dışında kontrolü aktarabileceği, ancak hiçbir zaman bloklara aktaramayacağı anlamına gelir. dipnot
Etiketlerin kendi bildirim alanları vardır ve diğer tanımlayıcıları engellemez.
Örnek: Örnek
int F(int x) { if (x >= 0) { goto x; } x = -x; x: return x; }geçerlidir ve hem parametre hem de etiket olarak x adını kullanır.
son örnek
Etiketlenmiş bir deyimin yürütülmesi, etiketi izleyen deyimin yürütülmesine tam olarak karşılık gelir.
Normal denetim akışı tarafından sağlanan erişilebilirliğe ek olarak, etiketli bir deyim, erişilebilir bir goto deyimi etikete başvuruda bulunursa erişilebilir olur, ancak bu goto deyimi, bitiş noktası ulaşılamayan bir try bloğu içeren ve etiketli deyimin catch dışında olduğu bir try_statement bloğunun finally bloğu veya bir bloğu içinde değilse.
13.6 Beyan ifadeleri
13.6.1 Genel
declaration_statement bir veya daha fazla yerel değişken, bir veya daha fazla yerel sabit ya da yerel işlev bildirir. Bildirim ifadelerine bloklarda ve switch bloklarında izin verilir, ancak gömülü ifadeler olarak izin verilmez.
declaration_statement
: local_variable_declaration ';'
| local_constant_declaration ';'
| local_function_declaration
;
Yerel değişken bir local_variable_declaration (§13.6.2) kullanılarak bildirilir. Yerel sabit, local_constant_declaration (§13.6.3) kullanılarak bildirilir. Yerel bir işlev local_function_declaration (§13.6.4) kullanılarak bildirilir.
Bildirilen adlar en yakın kapsayan bildirim alanına (§7.3) eklenir.
13.6.2 Yerel değişken bildirimleri
13.6.2.1 Genel
bir local_variable_declaration bir veya daha fazla yerel değişken bildirir.
local_variable_declaration
: implicitly_typed_local_variable_declaration
| explicitly_typed_local_variable_declaration
| explicitly_typed_ref_local_variable_declaration
;
Örtülü olarak belirlenen bildirimler bağlamsal anahtar kelimeyi (§6.4.4) var içerir ve bu da üç kategori arasında aşağıdaki gibi çözümlenen bir sözdizimsel belirsizliğe neden olur.
- Kapsam içinde adlı
varbir tür yoksa ve giriş implicitly_typed_local_variable_declaration eşleşiyorsa seçilir; - Aksi takdirde,
varadındaki bir tür kapsam dahilindeyse, implicitly_typed_local_variable_declaration olası bir eşleşme olarak değerlendirilmez.
Bir local_variable_declaration her değişken, sırasıyla örtük olarak yazılan, açıkça yazılan ve başvurulan yerel değişkenler için implicitly_typed_local_variable_declarator, explicitly_typed_local_variable_declarator veya ref_local_variable_declarator biri olan bir bildirimci tarafından sunulur. Bildirimci, tanıtılan değişkenin adını (tanımlayıcı) ve varsa ilk değerini tanımlar.
Bir bildirimde birden çok bildirimci varsa, bunlar soldan sağa doğru (§9.4.4.5) tüm başlatma ifadeleri de dahil olmak üzere işlenir.
Not: for_initializer (§13.9.4) veya resource_acquisition (§13.14) olarak gerçekleşmeyen bir local_variable_declaration için bu soldan sağa sıra, her bildirimcinin ayrı bir local_variable_declaration içinde olmasına eşdeğerdir. Örneğin:
void F() { int x = 1, y, z = x * 2; }eşdeğerdir:
void F() { int x = 1; int y; int z = x * 2; }dipnot
Yerel değişkenin değeri bir simple_name (§12.8.4) kullanılarak bir ifadede elde edilir. Değerinin elde edildiği her konuma kesinlikle bir yerel değişken (§9.4) atanmalıdır. Bir local_variable_declaration tarafından sunulan her yerel değişken başlangıçta atanmamış (§9.4.3). Bildirimcinin başlatma ifadesi varsa, tanıtılan yerel değişken bildirimcinin sonunda atanmış olarak sınıflandırılır (§9.4.4.5).
bir local_variable_declaration tarafından tanıtılan yerel değişkenin kapsamı aşağıdaki gibi tanımlanır (§7.7):
- Bildirim for_initializer olarak gerçekleşirse, kapsam for_initializer, for_condition, for_iterator ve embedded_statement'tır (§13.9.4);
- Eğer bildirim bir kaynak edinimi olarak gerçekleşirse, kapsam, using_statement (§13.14) ifadesinin semantik açıdan eşdeğer genişlemesinin en dış bloğudur.
- Aksi takdirde kapsam, bildirimin gerçekleştiği blok olur.
Bir yerel değişkene, ismini bildiren öğenin öncesinde veya bildirici ifadesinin içindeki herhangi bir başlatma ifadesi içinde metinsel bir konumda kullanmak bir hatadır. Yerel değişken kapsamında, aynı ada sahip başka bir yerel değişken, yerel işlev veya sabit bildirmek derleme zamanında hataya yol açar.
Bir ref yerel değişkeninin ref-safe-context (§9.7.2), onu başlatan değişken_referansı'nın ref-safe bağlamıdır. Başvuru (ref) olmayan yerel değişkenlerin güvenli bağlamı bildirim bloğudur.
13.6.2.2 Örtük olarak yazılan yerel değişken bildirimleri
implicitly_typed_local_variable_declaration
: 'var' implicitly_typed_local_variable_declarator
| ref_kind 'var' ref_local_variable_declarator
;
implicitly_typed_local_variable_declarator
: identifier '=' expression
;
Örtük olarak_tanımlanan_yerel_değişken_tanımı, bir adet yerel değişken olan kimliği tanıtır.
İfade veya değişken_atıf derleme zamanı türüne sahip olmalıdır. T İlk alternatif, ifadenin ilk değerine sahip bir değişken bildirir; türü T? null atanamaz bir başvuru türü olduğunda T , aksi takdirde türü şeklindedir T. İkinci alternatif, ilk değeri refvariable_reference olan bir ref değişkeni bildirir; eğer ref T? null atanamaz bir başvuru türüyse, türü T olur, aksi takdirde türü ref T olur. (ref_kind§15.6.1'de açıklanmıştır.)
Örnek:
var i = 5; var s = "Hello"; var d = 1.0; var numbers = new int[] {1, 2, 3}; var orders = new Dictionary<int,Order>(); ref var j = ref i; ref readonly var k = ref i;Yukarıdaki örtük olarak yazılan yerel değişken bildirimleri, aşağıdaki açıkça yazılan bildirimlere tam olarak eşdeğerdir:
int i = 5; string s = "Hello"; double d = 1.0; int[] numbers = new int[] {1, 2, 3}; Dictionary<int,Order> orders = new Dictionary<int,Order>(); ref int j = ref i; ref readonly int k = ref i;Aşağıda, örtük olarak yazılan yerel değişken bildirimleri yanlıştır:
var x; // Error, no initializer to infer type from var y = {1, 2, 3}; // Error, array initializer not permitted var z = null; // Error, null does not have a type var u = x => x + 1; // Error, anonymous functions do not have a type var v = v++; // Error, initializer cannot refer to v itselfson örnek
13.6.2.3 Açıkça yazılan yerel değişken bildirimleri
explicitly_typed_local_variable_declaration
: type explicitly_typed_local_variable_declarators
;
explicitly_typed_local_variable_declarators
: explicitly_typed_local_variable_declarator
(',' explicitly_typed_local_variable_declarator)*
;
explicitly_typed_local_variable_declarator
: identifier ('=' local_variable_initializer)?
;
local_variable_initializer
: expression
| array_initializer
;
bir explicitly_typed_local_variable_declaration belirtilen türe sahip bir veya daha fazla yerel değişken tanıtır.
Bir local_variable_initializer varsa, türü basit atama (§12.23.2) veya dizi başlatma (§17.7) kurallarına göre uygun olacaktır ve değeri değişkenin ilk değeri olarak atanır.
13.6.2.4 Açıkça yazılan ref yerel değişken bildirimleri
explicitly_typed_ref_local_variable_declaration
: ref_kind type ref_local_variable_declarators
;
ref_local_variable_declarators
: ref_local_variable_declarator (',' ref_local_variable_declarator)*
;
ref_local_variable_declarator
: identifier '=' 'ref' variable_reference
;
Başlangıç variable_reference tür türüne sahip olmalı ve başvuru ataması ile aynı gereksinimleri karşılamalıdır (§12.23.3).
ref_kindref readonly ise, bildirilmekte olan tanımlayıcılar salt okunur olarak ele alınan değişkenlere referanslardır. Aksi takdirde, ref_kindref ise, bildirilen tanımlayıcılar yazılabilir değişkenlere referans olmalıdır.
method_modifier ile bildirilen bir yöntem içinde veya yineleyici içinde (ref struct) bir başv yerel değişkeni veya türündekiasync bir değişkeni bildirmek derleme zamanı hatasıdır.
13.6.3 Yerel sabit bildirimleri
bir local_constant_declaration bir veya daha fazla yerel sabit bildirir.
local_constant_declaration
: 'const' type constant_declarators
;
constant_declarators
: constant_declarator (',' constant_declarator)*
;
constant_declarator
: identifier '=' constant_expression
;
local_constant_declaration'ın türü, bildirim tarafından tanıtılan sabitlerin türünü belirtir. Türün ardından her biri yeni bir sabit ekleyen constant_declaratorlistesi yer alır.
constant_declarator, sabiti adlandıran bir tanımlayıcı, ardından "=" belirteci ve ardından sabitin değerini veren bir constant_expression (§12.25) oluşur.
Yerel sabit bildirimin türü ve constant_expression , sabit üye bildiriminin (§15.4) kurallarıyla aynı kurallara uyacaktır.
Yerel sabitin değeri, simple_name (§12.8.4) kullanılarak bir ifadede elde edilir.
Yerel sabitin kapsamı, bildirimin gerçekleştiği blok olur. constant_declarator sonundan önce metinsel bir konumda yerel sabite başvurmak bir hatadır.
Birden çok sabit bildiren yerel sabit bildirimi, aynı türe sahip tek sabitlerin birden çok bildirimine eşdeğerdir.
13.6.4 Yerel işlev bildirimleri
bir local_function_declaration yerel bir işlev bildirir.
local_function_declaration
: local_function_modifier* return_type local_function_header
local_function_body
| ref_local_function_modifier* ref_kind ref_return_type
local_function_header ref_local_function_body
;
local_function_header
: identifier '(' parameter_list? ')'
| identifier type_parameter_list '(' parameter_list? ')'
type_parameter_constraints_clause*
;
local_function_modifier
: ref_local_function_modifier
| 'async'
;
ref_local_function_modifier
: 'static'
| unsafe_modifier // unsafe code support
;
local_function_body
: block
| '=>' null_conditional_invocation_expression ';'
| '=>' expression ';'
;
ref_local_function_body
: block
| '=>' 'ref' variable_reference ';'
;
Dil bilgisi notu: Bir local_function_body tanındığında hem null_conditional_invocation_expression hem de ifade alternatifleri geçerliyse, ilki seçilir. (§15.6.1)
Örnek: Yerel işlevler için iki yaygın kullanım örneği vardır: yineleyici yöntemleri ve zaman uyumsuz yöntemler. Yineleyici yöntemlerinde, tüm özel durumlar yalnızca döndürülen sırayı numaralandıran kod çağrılırken gözlemlenir. Zaman uyumsuz yöntemlerde, tüm özel durumlar yalnızca döndürülen Görev beklendiğinde gözlemlenir. Aşağıdaki örnek, yerel bir işlev kullanarak parametre doğrulamasını yineleyici uygulamasından ayırmayı gösterir:
public static IEnumerable<char> AlphabetSubset(char start, char end) { if (start < 'a' || start > 'z') { throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter"); } if (end < 'a' || end > 'z') { throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter"); } if (end <= start) { throw new ArgumentException( $"{nameof(end)} must be greater than {nameof(start)}"); } return AlphabetSubsetImplementation(); IEnumerable<char> AlphabetSubsetImplementation() { for (var c = start; c < end; c++) { yield return c; } } }son örnek
Aşağıda aksi belirtilmedikçe, tüm dil bilgisi öğelerinin semantiği, yöntem yerine yerel işlev bağlamında okunan method_declaration (§15.6.1) ile aynıdır.
Yerel_fonksiyon_bildiriminin tanımlayıcısı, kapsandığı tüm yerel değişken bildirim alanlarını da içeren bildirilen blok kapsamında benzersiz olmalıdır. Bunun bir sonucu olarak, aşırı yüklenmiş local_function_declaration'lere izin verilmemesidir.
bir local_function_declaration bir async (§15.14) değiştirici ve bir unsafe (§24.1) değiştirici içerebilir. Bildirim async değiştiricisini içeriyorsa dönüş türü void veya bir «TaskType» türü olmalıdır (§15.14.1). Bildirim değiştiriciyi static içeriyorsa işlev statik bir yerel işlevdir; aksi takdirde statik olmayan bir yerel işlevdir.
type_parameter_list veya parameter_listöznitelik içermesi derleme zamanı hatasıdır. Yerel işlev güvenli olmayan bir bağlamda (§24.2) bildirilirse, yerel işlev bildirimi değiştiriciyi içermese bile güvenli olmayan kod içerebilir unsafe .
Yerel bir işlev bir blok kapsamında bildirilir. Statik olmayan bir yerel işlev, kapsayan kapsamdan değişkenleri yakalayabilirken, statik bir yerel işlev bu nedenle kapsayan yerel değişkenlere, parametrelere, statik olmayan yerel işlevlere veya this erişimi olmadığı için yakalayamaz. Bir yakalanmış değişken, statik olmayan bir yerel işlevin gövdesi tarafından okunuyorsa ve bu değişkene işleve yapılan her çağrıdan önce kesinlikle bir atama yapılmadıysa, bu derleme zamanı hatası oluşur. Derleyici, dönüşte hangi değişkenlerin kesinlikle atandığını belirler (§9.4.4.33).
Türü this bir yapı türü olduğunda, yerel fonksiyonun gövdesinin this öğesine erişmesi derleme zamanı hatasıdır. Erişimin açık (this.xolduğu gibi) veya örtük (x'nin yapının örnek üyesi olduğu x olduğu gibi) olması durumu değiştirmez. Bu kural yalnızca bu tür bir erişimi yasaklar ve üye aramasının yapının bir üyesiyle sonuçlanıp sonuçlanmadığını etkilemez.
Yerel işlevin gövdesinde, hedefi yerel işlevin gövdesinin dışında olan bir goto deyimi, break deyimi veya continue deyimi bulunması derleme zamanı hatasıdır.
Not: Yukarıdaki kurallar
thisiçin vegoto§12.21.3'teki anonim işlevler için kuralları yansıtın. dipnot
Yerel işlev, bildiriminden önce sözcük temelli bir noktadan çağrılabilir. Ancak, işlevin yerel işlevde kullanılan bir değişkenin (§7.7) bildiriminden önce sözcük temelli olarak bildirilmesi bir derleme zamanı hatasıdır.
Bir yerel işlevin, herhangi bir kapsayıcı yerel değişken bildirim alanında belirtilen adla aynı ada sahip bir parametre, tür parametresi veya yerel değişken bildirmesi derleme zamanı hatasıdır.
Yerel işlev gövdelerine her zaman ulaşılabilir. Yerel işlev bildiriminin başlangıç noktasına ulaşılabilirse, yerel işlev bildiriminin uç noktasına ulaşılabilir.
Örnek: Aşağıdaki örnekte,
Lbaşlangıç noktası ulaşılabilir olmasa bileLgövdesine ulaşılabilir.Lbaşlangıç noktasına ulaşılamadığı içinLuç noktasını izleyen deyime erişilemez.class C { int M() { L(); return 1; // Beginning of L is not reachable int L() { // The body of L is reachable return 2; } // Not reachable, because beginning point of L is not reachable return 3; } }Başka bir deyişle, yerel işlev bildiriminin konumu, içeren işlevdeki deyimlerin erişilebilirliğini etkilemez. son örnek
Eğer yerel işlevin argümanının türü dynamic ise, çağrılacak işlevin derleme zamanında çözümlenmesi zorunludur, çalışma zamanında değil.
Bir ifade ağacında yerel işlev kullanılmamalıdır.
Statik yerel işlev
- Kapsayan kapsamdan statik üyelere, tür parametrelerine, sabit tanımlara ve statik yerel işlevlere başvurabilir.
- Örtük bir
thisbaşvurusundan veyabaseya dathisörnek üyelerinden, kapsayan kapsamdan yerel değişkenlere, parametrelere veya statik olmayan yerel işlevlere başvurulmamalıdır. Ancak, ifadedenameof()tüm bunlara izin verilir.
13.7 İfade deyimleri
expression_statement belirli bir ifadeyi değerlendirir. İfade ile hesaplanan değer (varsa) atılır.
expression_statement
: statement_expression ';'
;
statement_expression
: null_conditional_invocation_expression
| invocation_expression
| object_creation_expression
| assignment
| post_increment_expression
| post_decrement_expression
| pre_increment_expression
| pre_decrement_expression
| await_expression
;
İfadelerin tümüne deyim olarak izin verilmez.
Not: Özellikle, yalnızca bir değeri hesaplayan (atılacak) ve
x + ygibi ifadelere, deyim olarak izin verilmez. dipnot
bir expression_statement yürütülmesi, kapsanan ifadeyi değerlendirir ve ardından denetimi expression_statement bitiş noktasına aktarır. Bir expression_statement bitiş noktasına ulaşılabilir, eğer expression_statement ulaşılabilir ise.
13.8 Seçim ifadeleri
13.8.1 Genel
Seçim deyimleri, bazı ifadelerin değerine göre yürütme için bir dizi olası deyimden birini seçer.
selection_statement
: if_statement
| switch_statement
;
13.8.2 If deyimi
deyimi, if Boole ifadesinin değerine göre yürütme için bir deyim seçer.
if_statement
: 'if' '(' boolean_expression ')' embedded_statement
| 'if' '(' boolean_expression ')' embedded_statement
'else' embedded_statement
;
Bir else parçası, sözdiziminin izin verdiği sözcüksel olarak en yakın if ile bağlanır.
Örnek: Bu nedenle formun bir
ifdeyimiif (x) if (y) F(); else G();ile eşdeğer
if (x) { if (y) { F(); } else { G(); } }son örnek
Bir if ifadesi şu şekilde yürütülür:
- boolean_expression (§12.26) değerlendirilir.
- Boole ifadesi değerini verirse
true, denetim ilk katıştırılmış deyime aktarılır. Denetim bu deyimin bitiş noktasına ulaştığında ve olduğunda, denetim deyimininifbitiş noktasına aktarılır. - Boole ifadesi ortaya
falseçıkarsa ve birelseparça varsa, denetim ikinci katıştırılmış deyime aktarılır. Denetim bu deyimin bitiş noktasına ulaştığında ve olduğunda, denetim deyimininifbitiş noktasına aktarılır. - Boole ifadesi
falsesonucunu verirse ve birelsekısım yoksa, denetimifdeyiminin bitiş noktasına aktarılır.
Bir if deyiminin ilk eklenmiş deyimine ulaşılabilir, eğer if deyimi ulaşılabilirse ve Boole ifadesi sabit bir değere falsesahip değilse.
Eğer mevcutsa, bir if deyiminin ikinci katıştırılmış deyimi, if deyimi erişilebilir durumda olduğu ve Boole ifadesi true sabit değerine sahip olmadığı takdirde erişilebilir.
Eğer gömülü deyimlerinden en az birinin bitiş noktasına ulaşılabiliyorsa, bir if deyiminin bitiş noktasına da ulaşılabilir. Ek olarak, bir if deyiminin else parçası yoksa ve if deyimine ulaşılabiliyorsa, Boole ifadesinin sabit değeri true değilse, bu deyimin bitiş noktasına da ulaşılabilir.
13.8.3 Switch ifadesi
deyimi, anahtarın switchselector_expression değerine karşılık gelen ilişkili bir anahtar etiketine sahip bir deyim listesini yürütmeyi seçer.
switch_statement
: 'switch' selector_expression switch_block
;
selector_expression
: '(' expression ')'
| tuple_expression
;
switch_block
: '{' switch_section* '}'
;
switch_section
: switch_label+ statement_list
;
switch_label
: 'case' pattern case_guard? ':'
| 'default' ':'
;
case_guard
: 'when' null_coalescing_expression
;
switch_statement, anahtar sözcüğünden switchve ardından bir tuple_expression veya ayraçlı ifadeden (her biri selector_expression olarak adlandırılır) ve ardından bir switch_block oluşur.
switch_block, küme parantez içine alınmış sıfır veya daha fazla switch_section oluşur. Her switch_section bir veya daha fazla switch_label ve ardından bir statement_list (§13.3.2) oluşur. İçeren case her switch_label, anahtarın selector_expression değerinin test olduğu ilişkili bir desene (§11) sahiptir.
case_guard varsa, ifadesi örtük olarak türüne bool dönüştürülebilir olmalıdır ve bu ifade, vakanın karşılanmış sayılması için ek bir koşul olarak değerlendirilir.
Not: Kolaylık sağlamak için, selector_expression bir tuple_expression olduğunda switch_statement parantezler atlanabilir. Örneğin,
switch ((a, b)) …olarakswitch (a, b) …yazılabilir. dipnot
Deyimin switchidare türü, anahtarın selector_expression tarafından oluşturulur.
- Anahtarın selector_expression
sbytetürü , ,byte,short,ushort, ,int,uint,long,ulong, ,char, ,boolstringveya bir enum_type ise veya bu türlerden birine karşılık gelen null atanabilir değer türüyse, bu deyiminswitchidare türüdür. - Aksi takdirde, anahtarın selector_expression türünden aşağıdaki olası idare türlerinden birine tam olarak bir kullanıcı tanımlı örtük dönüştürme varsa:
sbyte,byte,short,ushort, ,int,uint, ,long,ulong, ,charstringveya, bu türlerden birine karşılık gelen null atanabilir bir değer türü, dönüştürülen tür deyiminswitchidare türüdür. - Aksi takdirde, deyiminin
switchidare türü anahtarın selector_expression türüdür. Böyle bir tür yoksa bu bir hatadır.
Bir default ifadesinde en fazla bir switch etiket olabilir.
Eğer herhangi bir anahtar etiketinin deseni, giriş ifadesinin türüne uygulanamazsa (§11.2.1), bu bir hatadır.
Anahtar deyimindeki herhangi bir anahtar etiketinin deseni, büyük/küçük harf koruyucusu olmayan veya büyük/küçük harf koruyucusu değeri true olan sabit bir ifade içeren, önceki anahtar etiketlerinin desenleri kümesi (§11.3) tarafından altında toplanırsa bir hatadır.
Örnek:
switch (shape) { case var x: break; case var _: // error: pattern subsumed, as previous case always matches break; default: break; // warning: unreachable, all possible values already handled. }son örnek
Bir switch ifadesi aşağıdaki gibi yürütülür:
- Anahtarın selector_expression değerlendirilir ve idare türüne dönüştürülür.
- Denetim, dönüştürülen anahtarın selector_expression değerine göre aktarılır:
- Anahtarın selector_expression değeriyle eşleşen ve guard ifadesinin eksik olduğu veya true olarak değerlendirildiği aynı
switchdeyimdeki etiket kümesindekicasesözcük temelli ilk desen, denetimin eşleşencaseetiketi izleyen deyim listesine aktarılmasına neden olur. - Aksi takdirde, bir
defaultetiketi varsa, kontroldefaultetiketinin ardından gelen deyim listesine aktarılır. - Aksi takdirde, kontrol
switchifadesinin bitiş noktasına aktarılır.
- Anahtarın selector_expression değeriyle eşleşen ve guard ifadesinin eksik olduğu veya true olarak değerlendirildiği aynı
Not: Çalışma zamanında desenlerin eşleşme sırası tanımlanmamıştır. Derleyicinin desenleri sıra dışı eşleştirmesine ve diğer desenlerin eşleşmesinin sonucunu hesaplamak için zaten eşleşen desenlerin sonuçlarını yeniden kullanmasına izin verilir (ancak gerekli değildir). Bununla birlikte, ifadeyle eşleşen ve guard yan tümcesinin eksik olduğu veya
trueolarak değerlendirildiği sözcük temelli ilk deseni belirlemek için bir derleyici gereklidir. dipnot
Switch bölümünün deyim listesinin bitiş noktasına ulaşılabiliyorsa, derleme zamanı hatası oluşur. Bu, "düşme yok" kuralı olarak bilinir.
Örnek: Örnek
switch (i) { case 0: CaseZero(); break; case 1: CaseOne(); break; default: CaseOthers(); break; }geçerli çünkü hiçbir geçiş bölümünün ulaşılabilir bir uç noktası yok. C ve C++'ın aksine, bir switch bölümünün yürütülmesinden sonra bir sonraki switch bölümüne "geçilmesine" izin verilmez ve örnek
switch (i) { case 0: CaseZero(); case 1: CaseZeroOrOne(); default: CaseAny(); }Bu, derleme zamanı hatasıyla sonuçlanır. Bir anahtar bölümünün yürütülmesini başka bir anahtar bölümünün yürütülmesi izleyecekse, açıkça bir
goto caseveyagoto defaultdeyimi kullanılmalıdır:switch (i) { case 0: CaseZero(); goto case 1; case 1: CaseZeroOrOne(); goto default; default: CaseAny(); break; }son örnek
Bir switch_section içinde birden fazla etiket kullanılabilir.
Örnek: Örnek
switch (i) { case 0: CaseZero(); break; case 1: CaseOne(); break; case 2: default: CaseTwo(); break; }geçerli. Etiketler
case 2:vedefault:aynı switch_section parçası olduğundan, örnek "geçilmez" kuralını ihlal etmez.son örnek
Not: "Geçiş yok" kuralı, ifadelere yanlışlıkla yer verilmediğinde C ve C++ dillerinde sık rastlanan bir hata türünü önler. Örneğin, yukarıdaki deyimin
switchbölümleri, deyiminin davranışını etkilemeden tersine çevrilebilir:switch (i) { default: CaseAny(); break; case 1: CaseZeroOrOne(); goto default; case 0: CaseZero(); goto case 1; }dipnot
Not: Switch bölümünün deyim listesi genellikle bir
break,goto caseveyagoto defaultdeyimiyle biter, ancak deyim listesinin bitiş noktasını erişilemez hale getiren herhangi bir yapıya izin verilir. Örneğin, Boole ifadesi tarafından denetlenen birwhiledeyiminintruehiçbir zaman bitiş noktasına ulaşmadığı bilinmektedir. Benzer şekilde, birthrowveyareturndeyimi denetimi her zaman başka bir yere aktarır ve hiçbir zaman bitiş noktasına ulaşmaz. Bu nedenle, aşağıdaki örnek geçerlidir:switch (i) { case 0: while (true) { F(); } case 1: throw new ArgumentException(); case 2: return; }dipnot
Örnek: Deyimin
switchidare türü türüstringolabilir. Örneğin:void DoCommand(string command) { switch (command.ToLower()) { case "run": DoRun(); break; case "save": DoSave(); break; case "quit": DoQuit(); break; default: InvalidCommand(command); break; } }son örnek
Not: Dize eşitliği işleçleri (§12.14.8)
switchgibi deyim de büyük/küçük harfe duyarlıdır ve yalnızca anahtarın selector_expression dizesi bir etiket sabiti ile tam olarak eşleşiyorsa belirli bircaseanahtar bölümünü yürütür. dipnot
Bir switch deyiminin idare türü veya null atanabilir bir değer türü olduğunda string , değere null etiket sabiti case olarak izin verilir.
Bir switch_block'un statement_list'i bildirim deyimleri (§13.6) içerebilir. Yerel değişkenin veya anahtar bloğunda bildirilen sabitin kapsamı anahtar bloğudur.
Aşağıdakilerden en az biri doğruysa anahtar etiketine ulaşılabilir:
- Anahtarın selector_expression sabit bir değerdir ve
- etiket, deseninin bu değerle
case(§11.2.1) bir 'dir ve etiketin koruyucusu ya mevcut değildir ya da değeri false olan sabit bir ifade değildir; veya - bu bir
defaultetikettir ve hiçbir anahtar bölümü, deseni bu değerle eşleşebilecek, koruyucusu ya eksik olan ya da true değerine sahip bir sabit ifade içeren bir durum etiketi içermez.
- etiket, deseninin bu değerle
- Anahtarın selector_expression sabit bir değer değildir ve
- etiket,
casedeğeri false sabiti olmayan, korumasız veya koruyucusu olmayan bir etikettir; veya - bu bir
defaultetikettir ve- değeri sürekli true olan bir korumaya sahip olan veya olmayan, switch deyiminin durumları arasında görünen desen kümesi, switch yöneten tür için kapsamlı değildir (§11.4); veya
- Anahtar kontrol türü, null atanabilir bir türdür ve koruması olmayan veya değeri true sabiti olan korumalara sahip switch deyiminin durumları arasında görünen desen kümesi,
nullile eşleşecek bir desen içermez.
- etiket,
- Anahtar etiketi, erişilebilir bir
goto caseveyagoto defaultdeyimi tarafından referans alınır.
Belirli bir switch bölümünün deyim listesi erişilebilir durumdaysa switch deyimi erişilebilir olmalı ve switch bölümü erişilebilir bir switch etiketi içermelidir.
Eğer switch deyimine ulaşılabiliyorsa ve aşağıdakilerden en az biri doğruysa, bir switch deyiminin bitiş noktasına ulaşılabilir.
-
switchdeyiminin içinde,breakdeyiminden çıkan erişilebilir birswitchdeyimi vardır. - Ya hiç
defaultetiketi yok veya- Anahtarın selector_expression sabit olmayan bir değerdir ve değeri true sabiti olan korumaları olmayan veya koruyucuları olmayan switch deyimi durumları arasında görünen desen kümesi, anahtar idare türü için kapsamlı değildir (§11.4).
- Anahtarın selector_expression , null atanabilir bir türün sabit olmayan bir değeridir ve değeri true sabiti olan korumaları olmayan veya korumaları olan switch deyiminin durumları arasında hiçbir desen görüntülenmez
null. - Anahtarın selector_expression sabit bir değerdir ve koruması olmayan veya koruyucusu true sabiti olan hiçbir
caseetiket bu değerle eşleşmez.
Örnek: Aşağıdaki kod, yan tümcesinin
whenkısa bir kullanımını gösterir:static object CreateShape(string shapeDescription) { switch (shapeDescription) { case "circle": return new Circle(2); … case var o when string.IsNullOrWhiteSpace(o): return null; default: return "invalid shape description"; } }Var durumu,
null, boş dize veya yalnızca boşluk içeren herhangi bir dizeyle eşleşir. son örnek
13.9 Yineleme ifadeleri
13.9.1 Genel
Yineleme deyimleri, katıştırılmış bir deyimi tekrar tekrar yürütür.
iteration_statement
: while_statement
| do_statement
| for_statement
| foreach_statement
;
13.9.2 While deyimi
while deyimi, gömülü bir deyimi koşullu olarak sıfır veya daha fazla kez yürütür.
while_statement
: 'while' '(' boolean_expression ')' embedded_statement
;
Bir while ifadesi aşağıdaki gibi yürütülür:
- boolean_expression (§12.26) değerlendirilir.
- Boole ifadesi
truesonuç verirse, kontrol gömülü deyime aktarılır. Denetim, ekli deyimin bitiş noktasına ulaştığında ve eğer bu bircontinuedeyiminin yürütülmesinden kaynaklanıyorsa, denetimwhiledeyiminin başına aktarılır. - Boole ifadesi değerini verirse
false, denetim deyimininwhilebitiş noktasına aktarılır.
Bir while deyiminin katıştırılmış deyiminde, denetimi deyimin bitiş noktasına break aktarmak için bir deyim (while) kullanılabilir (böylece eklenmiş deyimin yinelenmesi sona erer) ve denetimi katıştırılmış deyimin bitiş noktasına aktarmak için bir continue deyim (§13.10.3) kullanılabilir (böylece deyimin başka bir yinelemesini while gerçekleştirir).
Bir while deyiminin katıştırılmış deyimine ulaşılabilir, eğer while deyimi ulaşılabilirse ve Boole ifadesi sabit bir değere false sahip değilse.
Aşağıdakilerden en az biri doğruysa deyiminin while bitiş noktasına ulaşılabilir:
-
whiledeyiminin içinde,breakdeyiminden çıkan erişilebilir birwhiledeyimi vardır. -
whiledeyimine ulaşılabilir ve Boole ifadesi sabit değerinetruesahip değil.
13.9.3 Do deyimi
do deyimi, gömülü bir ifadeyi bir veya daha fazla kez koşullu olarak yürütür.
do_statement
: 'do' embedded_statement 'while' '(' boolean_expression ')' ';'
;
Bir do ifadesi aşağıdaki gibi yürütülür:
- Kontrol, gömülü deyime aktarılır.
- Denetim ekli deyimin bitiş noktasına ulaştığında (büyük olasılıkla bir
continuedeyimin yürütülmesinden), boolean_expression (§12.26) değerlendirilir. Boolean ifadesinin sonucutrueise, denetimdodeyiminin başına aktarılır. Aksi takdirde, kontroldoifadesinin bitiş noktasına aktarılır.
Bir do deyiminin katıştırılmış deyiminde, denetimi deyimin bitiş noktasına break aktarmak için bir deyim (do) kullanılabilir (böylece eklenmiş deyimin yinelenmesi sona erer) ve denetimi katıştırılmış deyimin bitiş noktasına aktarmak için bir continue deyim (§13.10.3) kullanılabilir (böylece deyimin başka bir yinelemesini do gerçekleştirir).
Bir do deyimine ulaşılabiliyorsa, bir do deyiminin gömülü deyimine de ulaşılabilir.
Aşağıdakilerden en az biri doğruysa deyiminin do bitiş noktasına ulaşılabilir:
-
dodeyiminin içinde,breakdeyiminden çıkan erişilebilir birdodeyimi vardır. - Katıştırılmış deyiminin bitiş noktasına ulaşılabilir ve Boole ifadesi sabit değerine
truesahip değildir.
13.9.4 For deyimi
for deyimi, bir başlatma ifadeleri dizisini değerlendirir ve ardından, bir koşul doğru olduğunda, katıştırılmış bir deyimi tekrar tekrar yürütür ve bir yineleme ifadeleri dizisini değerlendirir.
for_statement
: 'for' '(' for_initializer? ';' for_condition? ';' for_iterator? ')'
embedded_statement
;
for_initializer
: local_variable_declaration
| statement_expression_list
;
for_condition
: boolean_expression
;
for_iterator
: statement_expression_list
;
statement_expression_list
: statement_expression (',' statement_expression)*
;
Varsa for_initializer bir local_variable_declaration (§13.6.2) veya virgülle ayrılmış statement_expression(§13.7) listesinden oluşur. Bir for_initializer tarafından bildirilen yerel değişkenin kapsamı for_initializer, for_condition, for_iterator ve embedded_statement içerir.
varsa for_condition bir boolean_expression (§12.26) olacaktır.
varsa, for_iterator virgülle ayrılmış bir statement_expression(§13.7) listesinden oluşur.
Bir for ifadesi aşağıdaki gibi yürütülür:
- Bir for_initializer varsa, değişken başlatıcıları veya deyim ifadeleri yazıldıkları sırayla yürütülür. Bu adım yalnızca bir kez gerçekleştirilir.
- For_condition varsa değerlendirilir.
-
for_condition bulunmuyorsa veya değerlendirme
true'i döndürürse, denetim gömülü deyime aktarılır. Denetim katıştırılmış deyimin bitiş noktasına ulaştığında (büyük olasılıkla bircontinuedeyimin yürütülmesinden), varsa for_iterator ifadeleri sırayla değerlendirilir ve yukarıdaki adımda for_condition değerlendirilmesinden başlayarak başka bir yineleme gerçekleştirilir. -
for_condition varsa ve değerlendirme sonuç verirse
false, denetim deyimininforbitiş noktasına aktarılır.
Bir for deyiminin katıştırılmış deyiminde, denetimi break deyiminin bitiş noktasına aktarmak için bir deyimi (for) kullanılabilir (böylece katıştırılan deyimin yinelenmesini sonlandırır) ve denetimi ekli deyimin bitiş noktasına aktarmak için bir continue deyimi (§13.10.3) kullanılabilir (böylece for_iterator'ü çalıştırır ve for ile başlayarak deyiminin başka bir yinelemesini gerçekleştirir).
for deyiminin gömülü deyimine, aşağıdakilerden biri doğruysa erişilebilir:
- İfade
forulaşılabilir ancak for_condition mevcut değil. -
fordeyimine ulaşılabilir ve bir for_condition bulunmaktadır ve sabit bir değere sahip değildir.
Aşağıdakilerden en az biri doğruysa deyiminin for bitiş noktasına ulaşılabilir:
-
fordeyiminin içinde,breakdeyiminden çıkan erişilebilir birfordeyimi vardır. -
fordeyimine ulaşılabilir ve bir for_condition bulunmaktadır ve sabit bir değere sahip değildir.
13.9.5 Foreach deyimi
13.9.5.1 Genel
foreach deyimi bir koleksiyonun öğelerini numaralandırır ve koleksiyonun her öğesi için gömülü bir deyimi çalıştırır.
foreach_statement
: 'await'? 'foreach' '(' ref_kind? local_variable_type identifier
'in' expression ')' embedded_statement
;
Foreach deyiminin local_variable_type ve tanımlayıcısı deyiminin yineleme değişkenini bildirir.
var Tanımlayıcı local_variable_type olarak verilirse ve adlandırılmış var bir tür kapsam içinde değilse, yineleme değişkeninin örtük olarak yazılan bir yineleme değişkeni olduğu söylenir ve türü aşağıda belirtildiği gibi deyimin foreach öğe türü olarak alınır.
Hem await hem de ref_kind bir foreach statement içinde mevcut olduğunda bir derleme zamanı hatasıdır.
foreach_statement hem ref hem de readonly'yi ya da hiçbirini içeriyorsa, yineleme değişkeni salt okunur olarak kabul edilir. Aksi takdirde, foreach_statementref içerip readonly olmadan ise, yineleme değişkeni yazılabilir bir değişkeni belirtir.
Yineleme değişkeni, gömülü deyimi kapsayan bir kapsama sahip yerel bir değişkene karşılık gelir. Bir foreach deyiminin yürütülmesi sırasında yineleme değişkeni, yinelemenin şu anda gerçekleştirilmekte olduğu koleksiyon öğesini temsil eder. Yineleme değişkeni salt okunur bir değişkeni belirtirse, katıştırılmış deyimin bunu değiştirmeye (atma veya ++ ve -- işleçleri aracılığıyla) ya da bunu başvuru veya çıkış parametresi olarak geçirmeye çalışması durumunda derleme zamanı hatası oluşur.
Bir foreach deyiminin derleme zamanı işlemesi önce ifadenin koleksiyon türünü (C), numaralandırıcı türünü (E) ve yineleme türünü (Tref Tveya ref readonly T) belirler.
Belirleme, zaman uyumlu ve zaman uyumsuz sürümler için benzerdir. Farklı yöntemlere ve dönüş türlerine sahip farklı arabirimler zaman uyumlu ve zaman uyumsuz sürümleri ayırt eder. Genel süreç aşağıdaki gibi devam eder. '«' ve '»' içindeki adlar, zaman uyumlu ve zaman uyumsuz yineleyiciler için gerçek adların yer tutucularıdır. «GetEnumerator», «MoveNext», «IEnumerable»T, «IEnumerator»<T> ve diğer ayrımlar için izin verilen türler zaman uyumlu < bir deyim için > ve zaman uyumsuz bir deyim için foreach içinde ayrıntılı olarak açıklandı.foreach
-
Xtürünün uygun bir «GetEnumerator» yöntemine sahip olup olmadığını belirleyin:- Tür üzerinde
X«GetEnumerator» tanımlayıcısıyla ve hiçbir tür bağımsız değişkeni olmadan üye araması gerçekleştirin. Üye araması bir eşleşme üretmiyorsa veya bir belirsizlik veya yöntem grubu olmayan bir eşleşme üretirse, 2. adımda açıklandığı gibi numaralandırılabilir bir arabirim olup olmadığını denetleyin. Üye arama bir yöntem grubu dışında bir şey üretirse veya eşleşme yoksa bir uyarı verilmesi önerilir. - Elde edilen yöntem grubunu ve boş bir bağımsız değişken listesini kullanarak aşırı yükleme çözümlemesi gerçekleştirin. Aşırı yükleme çözümlemesi geçerli bir yöntemle sonuçlanmıyorsa, belirsizlikle sonuçlanıyorsa veya tek bir en iyi yöntemle sonuçlanıyorsa ancak bu yöntem statikse veya genel değilse, aşağıda açıklandığı gibi numaralandırılabilir bir arabirim olup olmadığını denetleyin. Aşırı yükleme çözümlemesi belirsiz bir genel örnek yöntemi dışında bir şey üretirse veya geçerli yöntem yoksa bir uyarı verilmesi önerilir.
- «GetEnumerator» yönteminin dönüş türü
Ebir sınıf, yapı veya arabirim türü değilse, bir hata oluşturun ve başka bir adım atmayın. - Tanımlayıcıyla
Eve hiçbir tür bağımsız değişkeni olmadan üzerindeCurrentüye araması gerçekleştirin. Üye araması eşleşme üretmezse, sonuç bir hatadır veya sonuç, okumaya izin veren bir genel örnek özelliği dışında bir şey olur, hata üretir ve başka bir adım atması gerekmez. - «MoveNext» tanımlayıcısıyla ve hiçbir tür bağımsız değişkeni olmadan üzerinde üye araması
Egerçekleştirin. Üye araması eşleşme üretmezse, sonuç bir hatadır veya sonuç bir yöntem grubu dışında herhangi bir şeyse, bir hata oluşturun ve başka bir adım atmasın. - Yöntem grubunda boş bir bağımsız değişken listesiyle aşırı yükleme çözümlemesi gerçekleştirin. Aşırı yükleme çözümlemesi şu sonuçlara neden olursa: geçerli yöntem yok; bir belirsizlik; veya tek bir en iyi yöntemdir, ancak bu yöntem statiktir veya genel değildir ya da dönüş türü izin verilen bir dönüş türü değildir; ardından bir hata oluşturun ve başka bir adım atlayın.
- Koleksiyon türü
X, numaralandırıcı türüEve yineleme türüCurrentözelliğinin türüdür.
- Tür üzerinde
- Aksi takdirde, numaralandırılabilir bir arabirim olup olmadığını denetleyin:
- «IEnumerable»Ti'ye
Tᵢörtük dönüştürmeXolan tüm türler < arasında, olmayan benzersiz bir tür >TTvarsa ve diğerdynamicherkes için «IEnumerable»T'denTᵢ«IEnumerable»<>Ti'ye< örtük bir dönüştürme varsa, koleksiyon türü «IEnumerable»>T< arabirimidir, numaralandırıcı türü «IEnumerator»>T< arabirimidir,> ve yineleme türü şeklindedirT. - Aksi takdirde, birden fazla tür
Tvarsa, bir hata oluşturun ve başka bir adım atmasın.
- «IEnumerable»Ti'ye
Not: İfade
nulldeğerine sahipse, çalışma zamanında birSystem.NullReferenceExceptionfırlatılır. dipnot
Bir uygulamanın belirli bir foreach_statement farklı şekilde uygulamasına izin verilir; örneğin, davranış §13.9.5.2 ve §13.9.5.3'te açıklanan genişletmelerle tutarlı olduğu sürece performans nedeniyle.
13.9.5.2 Zaman uyumlu foreach
Zaman uyumlu foreach anahtar sözcüğü anahtar sözcüğünden await önce foreach içermez.
Koleksiyon türü, numaralandırma türü ve yineleme türünün belirlenmesi , §13.9.5.1'de açıklandığı gibi devam eder; burada:
- «GetEnumerator» bir
GetEnumeratoryöntemdir. - «MoveNext» dönüş türüne sahip bir
MoveNextyöntemdirbool. - «IEnumerable»<T> arabirimidir
System.Collections.Generic.IEnumerable<T>. - «IEnumerator»<T> arabirimidir
System.Collections.Generic.IEnumerator<T>.
Ayrıca , §13.9.5.1'deki adımlarda aşağıdaki değişiklikler yapılır:
§13.9.5.1'de açıklanan işlemden önce aşağıdaki adımlar atılır:
-
Xİfade türü bir dizi türüyse, dizininXöğe türü olanIEnumerable<T>arabirimeT(X) örtük başvuru dönüştürmesi vardır. - Eğer
Xtürüdynamicise, o zaman ifadesi’denIEnumerablearabirimine (§10.2.10) örtük bir dönüştürme vardır. Koleksiyon türüIEnumerablearabirimi, numaralandırıcı türü iseIEnumeratorarabirimidir.varTanımlayıcı local_variable_type olarak verilirse yineleme türü olurdynamic, aksi takdirde olurobject.
§13.9.5.1 içindeki işlem tek bir koleksiyon türü, numaralandırıcı türü ve yineleme türü oluşturmadan tamamlanırsa aşağıdaki adımlar uygulanır:
- arabirimine
XSystem.Collections.IEnumerableörtük bir dönüştürme varsa, koleksiyon türü bu arabirimdir, numaralandırıcı türü arabirimidirSystem.Collections.IEnumeratorve yineleme türü olurobject. - Aksi takdirde bir hata oluşturulur ve başka bir adım atılmaz.
foreach biçiminde bir ifade
foreach (V v in x) «embedded_statement»
daha sonra şu değerle eşdeğerdir:
{
E e = ((C)(x)).GetEnumerator();
try
{
while (e.MoveNext())
{
V v = (V)(T)e.Current;
«embedded_statement»
}
}
finally
{
... // Dispose e
}
}
Değişken e , ifade x veya ekli deyim ya da programın başka bir kaynak kodu için görünür veya erişilebilir değildir. Değişken v, gömülü deyimde salt okunurdur.
(yineleme türü) ile T arasında, V deyimindeki local_variable_type için açık bir dönüştürme (foreach) yoksa, bir hata üretilir ve başka bir adım atılmaz.
Yineleme değişkeni bir başvuru değişkeni olduğunda (§9.7), formun bir foreach deyimi
foreach (ref V v in x) «embedded_statement»
daha sonra şu değerle eşdeğerdir:
{
E e = ((C)(x)).GetEnumerator();
try
{
while (e.MoveNext())
{
ref V v = ref e.Current;
«embedded_statement»
}
}
finally
{
... // Dispose e
}
}
Değişken e , ifade x veya ekli deyim ya da programın başka bir kaynak kodu için görünür veya erişilebilir değildir. Başvuru değişkeni v ekli deyimde okuma-yazmadır, ancak v yeniden başvuru atanmamalıdır (§12.23.3). Eğer (yineleme türü) ile T (cümledeki V olan ) arasında bir kimlik dönüştürmesi (foreach) yoksa bir hata oluşturulur ve başka adım atılmaz.
foreach ifadesi foreach (ref readonly V v in x) «embedded_statement» şeklinde benzer bir karşılık forma sahiptir, ancak başvuru değişkeni katıştırılmış ifadede v olarak ref readonly bulunduğundan, yeniden atanamaz veya başka bir referans atanamaz.
Döngünün vwhile içine yerleştirilmesi, embedded_statement gerçekleşen herhangi bir anonim işlev tarafından nasıl yakalandığı (§12.21.6.2) için önemlidir.
Örnek:
int[] values = { 7, 9, 13 }; Action f = null; foreach (var value in values) { if (f == null) { f = () => Console.WriteLine("First value: " + value); } } f();Genişletilmiş formda
vdöngü dışında bildirilirse, tüm yinelemeler arasında paylaşılır vewhiledöngüsünden sonraki değeri, yani son değer, olur. Bu,forçağrısının yazdıracağı13değeridir. Bunun yerine, her yinelemenin kendi değişkenivolduğundan, ilk yinelemedeftarafından yakalanan değer, yazdırılacak olan değeri7tutmaya devam eder. (Önceki C# sürümlerindevifadesininwhiledöngüsü dışında bildirildiğine dikkat edin.)son örnek
finally bloğunun gövdesi aşağıdaki adımlara göre oluşturulur:
Eğer
E'denSystem.IDisposablearabirimine örtük bir dönüştürme varsa,Enull olamaz bir değer türüysefinallyyan tümcesi şu anlamsal eşdeğerine genişletilir:finally { ((System.IDisposable)e).Dispose(); }Aksi takdirde,
finallytümcesi aşağıdaki anlamsal eşdeğer hale genişletilir:finally { System.IDisposable d = e as System.IDisposable; if (d != null) { d.Dispose(); } }Ebir değer türü veya bir değer türüne örnekli bir tür parametresiyse,e'inSystem.IDisposable'ye dönüştürülmesi kutulamanın oluşmasına neden olmaz.
Aksi takdirde, korumalı bir türse
Eyanfinallytümcesi boş bir bloğa genişletilir:finally {}Aksi takdirde,
finallyyan tümcesi şu şekilde genişletilir:finally { System.IDisposable d = e as System.IDisposable; if (d != null) { d.Dispose(); } }
Yerel değişken d herhangi bir kullanıcı kodu için görünür veya erişilebilir değildir. Özellikle, kapsamı finally bloğunu içeren başka bir değişkenle çatışmaz.
Dizinin öğelerinin geçiş sırası foreach aşağıdaki gibidir: Tek boyutlu diziler için öğeleri dizin 0'dan başlayıp dizinle Length – 1biten dizin sırası artan şekilde geçirilir. Çok boyutlu diziler için, öğeler en sağdaki boyutun dizinleri önce artırılır, sonra bir sonraki sol boyut vb. sola doğru geçirilir.
Örnek: Aşağıdaki örnek, iki boyutlu dizideki her değeri öğe sırasına göre yazdırır:
class Test { static void Main() { double[,] values = { {1.2, 2.3, 3.4, 4.5}, {5.6, 6.7, 7.8, 8.9} }; foreach (double elementValue in values) { Console.Write($"{elementValue} "); } Console.WriteLine(); } }Üretilen çıkış aşağıdaki gibidir:
1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9son örnek
Örnek: Aşağıdaki örnekte
int[] numbers = { 1, 3, 5, 7, 9 }; foreach (var n in numbers) { Console.WriteLine(n); }
ntürünün,intolduğu,numbers'nın yineleme türü olarak tahmin edilir.son örnek
13.9.5.3 foreach bekleniyor
Zaman uyumsuz foreach söz dizimini await foreach kullanır.
Koleksiyon türü, numaralandırma türü ve yineleme türünün belirlenmesi , §13.9.5.1'de açıklandığı gibi devam eder; burada:
- «GetEnumerator», beklenebilir dönüş türüne (
GetEnumeratorAsync) sahip bir yöntemdir. - «MoveNext»,
MoveNextAsyncawait_expression (§12.9.9.3) olarak sınıflandırıldığı, beklenebilir dönüş türüne (§12.9.9.2) sahip birboolyöntemdir. - «IEnumerable»<T> arabirimidir
System.Collections.Generic.IAsyncEnumerable<T>. - «IEnumerator»<T> arabirimidir
System.Collections.Generic.IAsyncEnumerator<T>.
Bir deyiminin yineleme türününawait foreach başvuru değişkeni (§9.7) olması hatadır.
await foreach Formun deyimi
await foreach (T item in enumerable) «embedded_statement»
şu ifadelere eşdeğerdir:
var enumerator = enumerable.GetAsyncEnumerator();
try
{
while (await enumerator.MoveNextAsync())
{
T item = enumerator.Current;
«embedded_statement»
}
}
finally
{
// dispose of enumerator as described later in this clause.
}
İfadenin enumerable bir yöntem çağrı ifadesini temsil ettiği ve parametrelerden birinin (EnumeratorCancellationAttribute) ile CancellationToken işaretlendiği durumlarda, yöntemine GetAsyncEnumerator geçirilir. Diğer kitaplık yöntemleri için CancellationTokenbir GetAsyncEnumerator geçirilmesi gerekebilir. Bu yöntemler ifadenin enumerablebir parçası olduğunda, belirteçler ve CreateLinkedTokenSource özelliği gibi Token tek bir belirteçte birleştirilir.
finally bloğunun gövdesi aşağıdaki adımlara göre oluşturulur:
Dönüş türünün beklenebilir olduğu erişilebilir
Ebir yöntemi varsaDisposeAsync()(§12.9.9.2),finallyyan tümcesi şu anlamsal eşdeğerine genişletilir:finally { await e.DisposeAsync(); }Aksi takdirde, arabiriminden
ESystem.IAsyncDisposableörtük bir dönüştürme varsa veEnull değer türüfinallydeğilse yan tümcesi şu anlamsal eşdeğerine genişletilir:finally { await ((System.IAsyncDisposable)e).DisposeAsync(); }Ebir değer türü veya bir değer türüne örnekli bir tür parametresiyse,e'inSystem.IAsyncDisposable'ye dönüştürülmesi kutulamanın oluşmasına neden olmaz.Aksi takdirde, bir
Etürse ve erişilebilirref structbir yöntemi varsaDispose()yanfinallytümcesi şu anlamsal eşdeğerine genişletilir:finally { e.Dispose(); }Aksi takdirde, korumalı bir türse
Eyanfinallytümcesi boş bir bloğa genişletilir:finally {}Aksi takdirde,
finallyyan tümcesi şu şekilde genişletilir:finally { System.IAsyncDisposable d = e as System.IAsyncDisposable; if (d != null) { await d.DisposeAsync(); } }
Yerel değişken d herhangi bir kullanıcı kodu için görünür veya erişilebilir değildir. Özellikle, kapsamı finally bloğunu içeren başka bir değişkenle çatışmaz.
Not:
await foreachZaman uyumsuz bir atma mekanizması mevcut değilse zaman uyumlu olarak atmakeiçin gerekli değildir. dipnot
13.10 Jump ifadeleri
13.10.1 Genel
Jump deyimleri koşulsuz olarak denetimi aktarır.
jump_statement
: break_statement
| continue_statement
| goto_statement
| return_statement
| throw_statement
;
Atlama deyiminin denetimi aktardığı konum, atlama deyiminin hedefi olarak adlandırılır.
Bir atlama deyimi bir blok içinde gerçekleştiğinde ve bu atlama deyiminin hedefi bu bloğun dışında olduğunda, atlama deyiminin bloktan çıktığı söylenir. Atlama deyimi kontrolü bir bloğun dışına aktarırken, hiçbir zaman kontrolü bir bloğa aktaramaz.
Atlama ifadelerinin yürütülmesi, araya giren try ifadelerin varlığıyla karmaşıklaşır. Bu tür try deyimlerin olmaması halinde, bir atlama deyimi, denetimi atlama deyiminden hedefine koşulsuz olarak aktarır. Bu tür araya giren try deyimlerin varlığında yürütme daha karmaşıktır. Atlama deyimi, ilişkili try bloklara sahip bir veya daha fazla finally bloktan çıkarsa, denetim başlangıçta finally deyimin en içteki try bloğuna aktarılır. Bir finally bloğunun bitiş noktasına ulaşıldığında ve bu gerçekleştiğinde, kontrol bir sonraki kapsayan finally deyiminin try bloğuna aktarılır. Bu işlem, tüm araya gelen finally ifadelerin try blokları yürütülene kadar yinelenir.
Örnek: Aşağıdaki kodda
class Test { static void Main() { while (true) { try { try { Console.WriteLine("Before break"); break; } finally { Console.WriteLine("Innermost finally block"); } } finally { Console.WriteLine("Outermost finally block"); } } Console.WriteLine("After break"); } }
finallyikitrydeyimle ilişkili bloklar, denetim atlama deyiminin hedefine aktarilmeden önce yürütülür. Üretilen çıkış aşağıdaki gibidir:Before break Innermost finally block Outermost finally block After breakson örnek
13.10.2 Break ifadesi
En yakın kapsayan break, switch, while, do veya for deyiminden foreach deyimi çıkar.
break_statement
: 'break' ';'
;
Bir break deyiminin hedefi, en yakın kapsayan switch, , whiledo, forveya foreach deyiminin bitiş noktasıdır. Bir break deyimi switch, while, do, for veya foreach deyimiyle kapatılmazsa, derleme hatası oluşur.
Birden çok switch, while, do, , forveya foreach deyimi iç içe geçtiğinde, bir break deyim yalnızca en içteki deyim için geçerlidir. Denetimi birden çok iç içe geçme düzeyinde aktarmak için bir goto deyim (§13.10.4) kullanılmalıdır.
Bir break ifade bir finally bloktan (§13.11) çıkış yapamaz. Bir break deyim bir finally blok içinde gerçekleştiğinde, deyiminin break hedefi aynı finally blok içinde olmalıdır; aksi takdirde bir derleme zamanı hatası oluşur.
Bir break ifadesi aşağıdaki gibi yürütülür:
- Eğer
breakdeyimi, ilişkilitrybloklarla bir veya daha fazlafinallybloktan çıkarsa, denetim başlangıçta en içtekifinallydeyiminintrybloğuna aktarılır. Birfinallybloğunun bitiş noktasına ulaşıldığında ve bu gerçekleştiğinde, kontrol bir sonraki kapsayanfinallydeyiminintrybloğuna aktarılır. Bu işlem, tüm araya gelenfinallyifadelerintryblokları yürütülene kadar yinelenir. - Denetim,
breakdeyiminin hedefine aktarılır.
Bir break deyim, denetimi koşulsuz olarak başka bir yere aktardığından, deyiminin break bitiş noktasına hiçbir zaman ulaşılamaz.
13.10.3 Continue deyimi
continue deyimi, en yakın kapsayan while, do, for veya foreach deyiminin yeni bir yinelemesini başlatır.
continue_statement
: 'continue' ';'
;
continue deyiminin hedefi, en yakın kapsayan while, do, for veya foreach deyiminin gömülü deyiminin bitiş noktasıdır. Bir continue deyimi, while, do, for veya foreach deyimiyle kapatılmazsa, derleme zamanı hatası oluşur.
Birden çok while, do, forveya foreach deyimi birbirinin içine yerleştirildiğinde, bir continue deyim yalnızca en içteki deyime uygulanır. Denetimi birden çok iç içe geçme düzeyinde aktarmak için bir goto deyim (§13.10.4) kullanılmalıdır.
Bir continue ifade bir finally bloktan (§13.11) çıkış yapamaz. Bir continue deyim bir finally blok içinde gerçekleştiğinde, deyiminin continue hedefi aynı finally blok içinde olmalıdır; aksi takdirde bir derleme zamanı hatası oluşur.
Bir continue ifadesi aşağıdaki gibi yürütülür:
- Eğer
continuedeyimi, ilişkilitrybloklarla bir veya daha fazlafinallybloktan çıkarsa, denetim başlangıçta en içtekifinallydeyiminintrybloğuna aktarılır. Birfinallybloğunun bitiş noktasına ulaşıldığında ve bu gerçekleştiğinde, kontrol bir sonraki kapsayanfinallydeyiminintrybloğuna aktarılır. Bu işlem, tüm araya gelenfinallyifadelerintryblokları yürütülene kadar yinelenir. - Denetim,
continuedeyiminin hedefine aktarılır.
Bir continue deyim, denetimi koşulsuz olarak başka bir yere aktardığından, deyiminin continue bitiş noktasına hiçbir zaman ulaşılamaz.
13.10.4 Goto deyimi
goto ifadesi, kontrolü bir etiketle işaretlenmiş olan başka bir deyime aktarır.
goto_statement
: 'goto' identifier ';'
| 'goto' 'case' constant_expression ';'
| 'goto' 'default' ';'
;
goto
deyiminin hedefi, belirtilen etikete sahip etiketli deyimdir. Verilen ada sahip bir etiket şu anki fonksiyon üyesinde yoksa veya goto ifadesi etiket kapsamında değilse, derleme sırasında bir hata oluşur.
Not: Bu kural, iç içe geçmiş bir
gotodenetimi aktarmak için bir deyimin kullanılmasına izin verir, ancak iç içe geçmiş bir kapsama aktarılmaz. Örnekteclass Test { static void Main(string[] args) { string[,] table = { {"Red", "Blue", "Green"}, {"Monday", "Wednesday", "Friday"} }; foreach (string str in args) { int row, colm; for (row = 0; row <= 1; ++row) { for (colm = 0; colm <= 2; ++colm) { if (str == table[row,colm]) { goto done; } } } Console.WriteLine($"{str} not found"); continue; done: Console.WriteLine($"Found {str} at [{row}][{colm}]"); } } }bir
gotoifadeyi iç içe geçmiş bir kapsamın dışına denetim aktarmak için kullanılır.dipnot
Deyimin goto case hedefi, verilen sabit değerin sabit desenine ve koruyucu olmayan bir switch etikete sahip bir deyim listesi içeren hemen üstteki deyimidir (case).
goto case Deyimi bir switch deyimi içine alınmamışsa, en yakın kapsayan switch deyim böyle bir case içermediyse veya constant_expression örtük olarak en yakın kapsayan deyimin yöneten türüne dönüştürülebilir değilse (switch), bir derleme zamanı hatası oluşur.
goto default ifadesinin hedefi, switch etiketini içeren deyim listesini barındıran en yakın ifadesidir (default).
goto default deyimi bir switch deyiminin içine alınmamışsa veya en yakın kapsayan switch deyim bir default etiket içermiyorsa, derleme zamanı hatası oluşur.
Bir goto ifade bir finally bloktan (§13.11) çıkış yapamaz. Bir goto deyim bir finally blok içinde gerçekleştiğinde, deyimin goto hedefi aynı finally blok içinde olacaktır veya başka bir şekilde derleme zamanı hatası oluşur.
Bir goto ifadesi aşağıdaki gibi yürütülür:
- Eğer
gotodeyimi, ilişkilitrybloklarla bir veya daha fazlafinallybloktan çıkarsa, denetim başlangıçta en içtekifinallydeyiminintrybloğuna aktarılır. Birfinallybloğunun bitiş noktasına ulaşıldığında ve bu gerçekleştiğinde, kontrol bir sonraki kapsayanfinallydeyiminintrybloğuna aktarılır. Bu işlem, tüm araya gelenfinallyifadelerintryblokları yürütülene kadar yinelenir. - Denetim,
gotodeyiminin hedefine aktarılır.
Bir goto deyim, denetimi koşulsuz olarak başka bir yere aktardığından, deyiminin goto bitiş noktasına hiçbir zaman ulaşılamaz.
13.10.5 Return deyimi
Dönüş deyimi, isteğe bağlı olarak bir değer veya return (§9.5) döndürebilir ve dönüş deyiminin geçtiği işlev üyesinin mevcut çağıranına kontrolü geri döndürür.
return_statement
: 'return' ';'
| 'return' expression ';'
| 'return' 'ref' variable_reference ';'
;
İfade içermeyen bir return_statementdeğer döndürmeyen olarak adlandırılır; refifade içeren birine referansla dönüş denir; ve sadece ifade içeren birinedeğerle dönüş denir.
Çıktı olarak değer döndürmeyen bir metodu, değere göre veya başvuruya göre dönen (başv) olarak bildirildiği durumlarda kullanmak derleme zamanı hatasıdır (§15.6.1).
Değer döndürmeyen veya değer döndüren olarak bildirilen bir yöntemden referansla dönüş kullanılması derlemede bir hataya yol açar.
Değer döndürmeyen veya referansla dönen olarak tanımlanmış bir yöntemden değer döndürme kullanmak derleme zamanı hatasıdır.
İfade bir variable_reference değilse veya ref-güvenli bağlamı çağıran bağlamla aynı olmayan bir değişkene referanssa (§9.7.2), referansla dönen bir dönüş kullanmak derleme zamanı hatasıdır.
method_modifierasync ile bildirilen bir yöntemden referans döndüren bir dönüş kullanmak derleme zamanı hatasıdır.
İşlev üyesinin, değere göre dönüş yöntemi (§15.6.11), bir özellik veya dizin oluşturucunun değere göre dönüş alma erişimcisi veya kullanıcı tanımlı işleci olan bir yöntemse değeri hesapladığı söylenir. Değer döndürmeyen işlev üyeleri bir değeri hesaplamaz ve etkin dönüş türüne voidsahip yöntemlerdir, özelliklerin ve dizin oluşturucuların erişimcilerini ayarlar, olayların erişimcilerini, örnek oluşturucularını, statik oluşturucuları ve sonlandırıcıları ekleyip kaldırır. Referans olarak dönen işlev üyeleri bir değeri hesaplamaz.
Değere dönüş için, ifade türünden içeren işlev üyesinin etkin dönüş türüne (§15.6.11) örtük dönüştürme (§10.2) bulunacaktır. Başvuru ile dönüş için, ifade türü ile içeren işlev üyesinin etkin dönüş türü arasında bir kimlik dönüştürmesi (§10.2.2) bulunmalıdır.
return deyimleri anonim işlev ifadelerinin gövdesinde de kullanılabilir (§12.21) ve bu işlevler için hangi dönüştürmelerin mevcut olduğunu belirlemeye katılabilir (§10.7.1).
Bir return deyiminin bir finally bloğunda görünmesi bir derleme zamanı hatasıdır (§13.11).
Bir return ifadesi aşağıdaki gibi yürütülür:
- Bir değere dönüş için ifade değerlendirilir ve değeri örtük bir dönüştürme ile içeren işlevin etkin dönüş türüne dönüştürülür. Dönüştürmenin sonucu, işlev tarafından üretilen sonuç değeri olur. "Referansla dönüş için, ifade değerlendirilir ve sonuç bir değişken olarak sınıflandırılmalıdır." Eğer kapsayan yöntemin başvuru ile dönüşü
readonlyiçeriyorsa, sonuçta elde edilen değişken salt okunurdur. - Deyim, bir veya daha fazla
returnveyatryblokla birlikte ilişkilicatchblokların içine alınmışsa, denetim başlangıçta en içtekifinallydeyiminfinallybloğuna aktarılır. Birfinallybloğunun bitiş noktasına ulaşıldığında ve bu gerçekleştiğinde, kontrol bir sonraki kapsayanfinallydeyiminintrybloğuna aktarılır. Bu işlem, tüm kapsayıcıfinallydeyimlerintryblokları yürütülene kadar yinelenir. - İçeren işlev zaman uyumsuz bir işlev değilse, denetim varsa sonuç değeriyle birlikte içeren işlevin çağırıcısına döndürülür.
- Bu işlevi içeren işlev bir async işlevse, kontrol mevcut çağırıcıya geri döner ve varsa sonuç değeri, (§15.14.3) içinde açıklandığı gibi dönüş görevine yazılır.
Bir return deyim, denetimi koşulsuz olarak başka bir yere aktardığından, deyiminin return bitiş noktasına hiçbir zaman ulaşılamaz.
13.10.6 Throw deyimi
throw ifadesi bir istisna oluşturur.
throw_statement
: 'throw' expression? ';'
;
İfade içeren bir throw deyimi, ifadenin değerlendirilmesiyle üretilen özel bir durum fırlatır. İ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. Dönüştürmenin sonucu null ise, bunun yerine bir System.NullReferenceException atılır.
throw İfade içermeyen bir deyim yalnızca bir catch blokta kullanılabilir, bu durumda bu deyim şu anda bu catch blok tarafından işlenen istisnayı yeniden fırlatır.
Bir throw deyim, denetimi koşulsuz olarak başka bir yere aktardığından, deyiminin throw bitiş noktasına hiçbir zaman ulaşılamaz.
Özel durum fırlatıldığında, denetim özel durumu işleyebilen bir kapsayıcı catch deyimdeki ilk try yan tümcesine aktarılır. Özel durumun oluştuğu noktadan denetimi uygun bir özel durum işleyicisine aktarma noktasına kadar geçen işlem, özel durum yayma olarak bilinir. Bir özel durumun yayılması, özel durumla eşleşen bir catch yan tümce bulunana kadar aşağıdaki adımların tekrar tekrar değerlendirilmesini içerir. Bu açıklamada, fırlatma noktası başlangıçta özel durumun fırlatıldığı konumdur. Bu davranış (§22.4) içinde belirtilir.
Geçerli fonksiyon üyesinde, atılan noktayı kapsayan her
trydeyim incelenir. Her bir ifadeSiçin, en içtekitryifadeden başlayarak en dıştakitryifadeye kadar, aşağıdaki adımlar değerlendirilir:- Eğer
trybloğuS, atma noktasını kapatıyorsa veSbir veya daha fazlacatchyan tümcesine sahipse,catchyan tümceler uygun bir işleyiciyi bulmak için görünüm sırasına göre incelenir. Çalışma zamanı türücatch,T'den türetiliyorsa bir eşleşme kabul edilen, bir özel durum türüT(veya çalışma zamanında bir özel durum türünü belirten tür parametresiE) tanımlayan ilkTyan tümce. Yan tümcesi bir özel durum filtresi içeriyorsa, özel durum nesnesi özel durum değişkenine atanır ve özel durum filtresi değerlendirilir. Bircatchyan tümce bir özel durum filtresi içerdiğinde, eğer bu özel durum filtresicatcholarak değerlendirilirse, butrueyan tümce eşleşme olarak kabul edilir. Genelcatch(§13.11) yan tümcesi, herhangi bir özel durum türü için eşleşme olarak kabul edilir. Eşleşencatchbir yan tümce bulunursa, denetimi bucatchyan tümcenin bloğuna aktararak özel durum yayma işlemi tamamlanır. - Aksi takdirde,
trybloğu veya bircatchbloğuSatma noktasını kapatıyorsa veS'ün birfinallybloğu varsa, denetimfinallybloğuna aktarılır.finallyBlok başka bir özel durum oluşturursa geçerli özel durumun işlenmesi sonlandırılır. Aksi takdirde, denetim bloğunfinallybitiş noktasına ulaştığında geçerli özel durumun işlenmesine devam edilir.
- Eğer
Geçerli işlev çağrısında bir özel durum işleyicisi bulunmadıysa, işlev çağrısı sonlandırılır ve aşağıdakilerden biri gerçekleşir:
Geçerli işlev zaman uyumsuz değilse, yukarıdaki adımlar, işlev üyesinin çağrıldığı deyime karşılık gelen bir fırlatma noktasıyla işlevi çağıran için yinelenir.
Geçerli işlev zaman uyumsuz ve görev döndürense, özel durum , §15.14.3'te açıklandığı gibi hatalı veya iptal edilmiş duruma konulan dönüş görevine kaydedilir.
Geçerli işlev senkronize olmayan ve
void-dönüşlü ise, geçerli iş parçacığının senkronizasyon bağlamı, §15.14.4'te açıklandığı gibi bildirilir.
Özel durum işleme geçerli iş parçacığındaki tüm işlev üyesi çağrılarını sonlandırırsa ve iş parçacığının özel durum için işleyicisi olmadığını gösterirse, iş parçacığının kendisi sonlandırılır. Bu sonlandırmanın etkisi uygulamaya bağlıdır.
13.11 Try deyimi
deyimi, try bir bloğun yürütülmesi sırasında oluşan özel durumları yakalamak için bir mekanizma sağlar. Ayrıca try deyimi, denetim try deyiminden ayrıldığında her zaman yürütülen bir kod bloğunu belirtme olanağı sağlar.
try_statement
: 'try' block catch_clauses
| 'try' block catch_clauses? finally_clause
;
catch_clauses
: specific_catch_clause+
| specific_catch_clause* general_catch_clause
;
specific_catch_clause
: 'catch' exception_specifier exception_filter? block
| 'catch' exception_filter block
;
exception_specifier
: '(' type identifier? ')'
;
exception_filter
: 'when' '(' boolean_expression ')'
;
general_catch_clause
: 'catch' block
;
finally_clause
: 'finally' block
;
try_statement anahtar sözcüğünden try sonra bir blok, ardından sıfır veya daha fazla catch_clauses ve ardından isteğe bağlı bir finally_clause oluşur. En az bir catch_clause veya finally_clause olacaktır.
Bir exception_specifier'da bulunan türü veya type_parameter ise geçerli temel sınıfı, System.Exception veya ondan türeyen bir tür olmalıdır.
Yan catch tümcesi hem class_type hem de tanımlayıcıyı belirttiğinde, verilen ad ve türün bir özel durum değişkeni bildirilir. Özel durum değişkeni , specific_catch_clause bildirim alanına (§7.3) eklenir.
exception_filter ve catch bloğun yürütülmesi sırasında, özel durum değişkeni şu anda işlenen özel durumu temsil eder. Kesin atama denetimi amacıyla, özel durum değişkeninin kapsamın tamamında kesinlikle atandığı kabul edilir.
Yan catch tümcesi bir özel durum değişkeni adı içermediği sürece, filtre ve catch bloktaki özel durum nesnesine erişmek mümkün değildir.
Ne catch bir özel durum türü ne de özel durum değişkeni adı belirten bir yan tümce genel catch yan tümcesi olarak adlandırılır. Bir try ifadenin yalnızca bir genel catch şartı olabilir ve varsa, son catch madde olacaktır.
Not: Bazı programlama dilleri, öğesinden
System.Exceptiontüretilen bir nesne olarak temsil edilemeyen özel durumları desteklese de, bu tür özel durumlar hiçbir zaman C# kodu tarafından oluşturulamaz. Bu tür özel durumları yakalamak için genelcatchbir ifade kullanılabilir. Bu nedenle, genel bircatchyan tümce, türünüSystem.Exceptionbelirten bir yan tümceden anlamsal olarak farklıdır; çünkü ilki, diğer dillerden gelen istisnaları da yakalayabilir. dipnot
Bir özel durumun işleyicisini bulmak için catch koşulları dizgisel sırayla incelenir. Aynı catch deyiminin önceki catch bloğu bir tür belirtiyor ancak özel durum filtresi içermiyorsa, sonraki try bloğunun bu türle aynı olan veya türetilmiş bir türü belirtmesi bir derleme zamanı hatasına neden olur.
Not Bu kısıtlama olmadan ulaşılamayan
catchkoşullar yazılabilir. dipnot
Bir catch blok içinde, throw bloğu tarafından yakalanmış olan istisnayı yeniden fırlatmak için ifade içermeyen bir deyimi (catch) kullanılabilir. Bir özel durum değişkenine yapılan atamalar, yeniden oluşan özel durumu değiştirmez.
Örnek: Aşağıdaki kodda
class Test { static void F() { try { G(); } catch (Exception e) { Console.WriteLine("Exception in F: " + e.Message); e = new Exception("F"); throw; // re-throw } } static void G() => throw new Exception("G"); static void Main() { try { F(); } catch (Exception e) { Console.WriteLine("Exception in Main: " + e.Message); } } }yöntemi
Fbir özel durum yakalar, konsola bazı tanılama bilgileri yazar, özel durum değişkenini değiştirir ve özel durumu yeniden oluşturur. Yeniden oluşturulan özel durum özgün özel durumdur, bu nedenle üretilen çıkış şöyledir:Exception in F: G Exception in Main: GEğer ilk
catchblok, geçerli özel durumu yeniden fırlatmak yerineefırlatsaydı, üretilen çıkış şöyle olurdu:Exception in F: G Exception in Main: Fson örnek
break, continue veya goto deyiminin, bir finally bloğunun dışına denetimi aktarması derleme zamanı hatasıdır. Bir break, continueveya goto deyimi bir finally blokta oluştuğunda, deyimin hedefi aynı finally blok içinde olacaktır veya başka bir şekilde derleme zamanı hatası oluşur.
Bir return deyiminin bir finally blok içinde yer alması derleme zamanı hatasıdır.
Yürütme bir try deyime ulaştığında, denetim bloğuna try aktarılır. Denetim, bir hata yayılmadan try bloğunun bitiş noktasına ulaşırsa, varsa kontrol finally bloğuna aktarılır. Blok finally yoksa, kontrol try deyiminin bitiş noktasına devredilir.
Bir istisna iletildiyse, catch belirtilmişse yan tümceler, istisna için ilk eşleşmeyi arayarak sözdizimsel sırayla incelenir. Eşleşen catch yan tümcenin aranması, §13.10.6'da açıklandığı gibi, tüm kapsayan bloklarla sürdürülür. Bir catch yan tümce, özel durum türü herhangi bir exception_specifier ile eşleştiğinde ve herhangi bir exception_filter doğru olduğunda eşleşir.
catch kabul yan tümcesi exception_specifier olmadan herhangi bir özel durum türüyle eşleşir. Özel durum türü, özel_durum_belirleyicisi özel durum türünü veya özel durum türünün temel türünü belirttiğinde özel_durum_belirleyicisi ile eşleşir. Yan tümcesi bir özel durum filtresi içeriyorsa, özel durum nesnesi özel durum değişkenine atanır ve özel durum filtresi değerlendirilir.
bir exception_filter için boolean_expression değerlendirmesi özel durum oluşturursa, bu özel durum yakalanırsa ve özel durum filtresi olarak falsedeğerlendirilir.
Bir özel durum yayılırsa ve eşleşen bir catch yan tümce bulunursa, denetim ilk eşleşen catch bloğa aktarılır. Denetim, bir hata yayılmadan catch bloğunun bitiş noktasına ulaşırsa, varsa kontrol finally bloğuna aktarılır. Blok finally yoksa, kontrol try deyiminin bitiş noktasına devredilir. Eğer bir istisna catch bloğundan yayılmışsa, bir finally bloğu mevcutsa, kontrol finally bloğuna aktarılır. Özel durum, sonraki kapsayan try deyime yayılır.
Bir özel durum yayılırsa ve eşleşen catch yan tümcesi bulunmazsa, finally bloğu varsa kontrol aktarılır. Özel durum, sonraki kapsayan try deyime yayılır.
finally bloğunun deyimleri, kontrol try deyiminden çıktığında her zaman yürütülür. Denetim aktarımının normal yürütmenin bir sonucu olarak, bir , break, continueveya deyiminin yürütülmesinin gotosonucu olarak veya return deyimin try dışına bir özel durum yayma sonucu olup olmadığı doğrudur. Denetim, bir özel durum yayılmadan bloğun finally bitiş noktasına ulaşırsa, denetim deyiminin try bitiş noktasına aktarılır.
Bir finally bloğunun yürütülmesi sırasında bir özel durum ortaya çıkarsa ve aynı finally blok içinde yakalanmazsa, bu özel durum bir sonraki kapsayıcı try deyime iletilir. Başka bir özel durum yayılma sürecindeyse, bu özel durum kaybolur. Özel durum yayma işlemi, deyiminin throw açıklamasında daha ayrıntılı olarak ele alınıyor (§13.10.6).
Örnek: Aşağıdaki kodda
public class Test { static void Main() { try { Method(); } catch (Exception ex) when (ExceptionFilter(ex)) { Console.WriteLine("Catch"); } bool ExceptionFilter(Exception ex) { Console.WriteLine("Filter"); return true; } } static void Method() { try { throw new ArgumentException(); } finally { Console.WriteLine("Finally"); } } }yöntemi
Methodbir özel durum oluşturur. İlk eylem, kapsayıcıcatchyan tümceleri inceleyerek ve herhangi bir özel durum filtresi yürütmektir. Ardından,finallyiçindekiMethodyan tümcesi, kontrol kapsayan eşleşencatchyan tümceye aktarılmadan önce yürütülür. Sonuçta elde edilen çıktı:Filter Finally Catchson örnek
try bloğu, try deyimine ulaşılabiliyorsa, bir try deyimine ulaşılabilir.
Deyimine catch ulaşılabilirse, try deyiminin bloğuna try ulaşılabilir.
finally bloğu, try deyimine ulaşılabiliyorsa, bir try deyimine ulaşılabilir.
Aşağıdakilerin her ikisi de doğruysa deyiminin try bitiş noktasına ulaşılabilir:
- Bloğun
trybitiş noktasına ulaşılabilir veya en az bircatchbloğun bitiş noktasına ulaşılabilir. - Bir
finallyblok varsa bloğunfinallybitiş noktasına ulaşılabilir.
13.12 İşaretli ve işaretlenmemiş deyimler
checked ve unchecked ifadeleri, tamsayı türü aritmetik işlemler ve dönüştürmeler için taşma denetleme bağlamını kontrol etmek için kullanılır.
checked_statement
: 'checked' block
;
unchecked_statement
: 'unchecked' block
;
checked deyimi, bloktaki tüm ifadelerin denetlenen bir bağlamda değerlendirilmesine neden olur ve unchecked deyimi, bloktaki tüm ifadelerin kontrolsüz bir bağlamda değerlendirilmesine neden olur.
checked ve unchecked ifadeleri, ifadeler yerine bloklar üzerinde çalışması dışında checked ve unchecked işleçlerine (§12.8.20) tam olarak eşdeğerdir.
13.13 Kilit deyimi
lock ifadesi belirli bir nesne için karşılıklı dışlama kilidini elde eder, ifadeyi yürütür ve sonra kilidi serbest bırakır.
lock_statement
: 'lock' '(' expression ')' embedded_statement
;
Bir deyiminin lock, başvuru olarak bilinen türde bir değeri belirtir.
deyiminin ifadesi için hiçbir örtük kutulama dönüşümü (lock) gerçekleştirilmez, bu nedenle ifadenin bir value_type değeri belirtmesi derleme zamanı hatasıdır.
lock biçiminde bir ifade
lock (x)...
burada x bir reference_type ifadesidir, tam olarak şunun eşdeğeridir:
bool __lockWasTaken = false;
try
{
System.Threading.Monitor.Enter(x, ref __lockWasTaken);
...
}
finally
{
if (__lockWasTaken)
{
System.Threading.Monitor.Exit(x);
}
}
ancak x yalnızca bir kez değerlendirilir.
Karşılıklı dışlama kilidi tutuluyorken, aynı yürütme iş parçacığında çalışan kod da kilidi alabilir ve serbest bırakabilir. Ancak, diğer iş parçacıklarında yürütülen kodun kilit serbest bırakılana kadar kilidi alması engellenir.
13.14 using deyimi
13.14.1 Genel
using deyimi, bir veya daha fazla kaynağı alır, bir deyimi yürütür ve ardından kaynakları atar.
using_statement
: 'await'? 'using' '(' resource_acquisition ')' embedded_statement
;
resource_acquisition
: non_ref_local_variable_declaration
| expression
;
non_ref_local_variable_declaration
: implicitly_typed_local_variable_declaration
| explicitly_typed_local_variable_declaration
;
Kaynak türü, ve/veya adlı System.IDisposable tek bir parametresiz yöntem içeren ya da tarafından bildirilenle System.IAsyncDisposableaynı imzaya sahip olan adlı bir yöntem Dispose içeren ya DisposeAsync da arabirimlerden birini ya da her ikisini Dispose uygulayan bir sınıf veya System.IDisposablebaşv olmayan yapıdır. Kaynak kullanan kod çağrısı Dispose yapabilir veya DisposeAsync kaynağın artık gerekli olmadığını belirtebilir.
resource_acquisition biçimi local_variable_declaration ise local_variable_declaration türü veya kaynak türü olmalıdırdynamic.
resource_acquisition biçimi ifade ise, bu ifadenin bir kaynak türü olmalıdır. Varsa await , kaynak türü uygulayacaktır System.IAsyncDisposable. Tür ref struct , değiştiriciye sahip bir using deyimin await kaynak türü olamaz.
Bir resource_acquisition'da tanımlanan yerel değişkenler salt okunur olup başlatıcı bir değer içermelidir. Katıştırılmış deyim bu yerel değişkenleri değiştirmeyi denerse (atama veya ++ ve -- işleçleri aracılığıyla), bunların adresini alırsa veya bunları başvuru veya çıkış parametresi olarak geçirirse derleme zamanı hatası oluşur.
Bir using deyim üç bölüme çevrilir: alım, kullanım ve elden çıkarma. Kaynağın kullanımı, bir try yan tümce içeren finally deyimi içine örtük olarak alınır. Bu finally madde kaynağın atılmasını sağlar. Alma ifadesi olarak değerlendirilirse null, çağrısı ( Dispose veya DisposeAsync) yapılmaz ve hiçbir özel durum atılır. Kaynak türündeyse dynamic , dönüştürmenin kullanım ve elden çıkarma işleminden önce başarılı olduğundan emin olmak için alım sırasında örtük bir dinamik dönüştürme (§10.2.10) IDisposable ile (veya IAsyncDisposable) dinamik olarak dönüştürülür.
using biçiminde bir ifade
using (ResourceType resource = «expression» ) «statement»
üç olası formülasyondan birine karşılık gelir. Sınıf ve başvuru olmayan yapı kaynakları için, null atanamaz bir değer türü veya değer türü kısıtlamasına (ResourceType) sahip bir tür parametresi olduğunda formülasyon, anlamsal olarak şuna eşdeğerdir:
{
ResourceType resource = «expression»;
try
{
«statement»;
}
finally
{
((IDisposable)resource).Dispose();
}
}
resource'nın System.IDisposable'e dökümünün boxing'e neden olmaması gerekir.
Aksi takdirde, olduğunda ResourceTypedynamicformülasyon
{
ResourceType resource = «expression»;
IDisposable d = resource;
try
{
«statement»;
}
finally
{
if (d != null)
{
d.Dispose();
}
}
}
Aksi takdirde formülasyon şu şekildedir:
{
ResourceType resource = «expression»;
try
{
«statement»;
}
finally
{
IDisposable d = (IDisposable)resource;
if (d != null)
{
d.Dispose();
}
}
}
Başvuru yapısı kaynakları için tek anlamsal eşdeğer formülasyon şudur:
{
«ResourceType» resource = «expression»;
try
{
«statement»;
}
finally
{
resource.Dispose();
}
}
Herhangi bir formülasyonda resource , değişken katıştırılmış deyimde salt okunurdur ve d değişkenine erişilemez ve ekli deyimde görünmez.
using yapısında bir ifade:
using («expression») «statement»
aynı formülasyonlara sahiptir.
resource_acquisition bir local_variable_declaration biçimini aldığında, belirli bir türde birden çok kaynak elde etmek mümkündür.
using biçiminde bir ifade
using (ResourceType r1 = e1, r2 = e2, ..., rN = eN) «statement»
tam anlamıyla iç içe geçmiş using ifade dizisine eşdeğerdir:
using (ResourceType r1 = e1)
using (ResourceType r2 = e2)
...
using (ResourceType rN = eN)
«statement»
Örnek: Aşağıdaki örnek log.txt adlı bir dosya oluşturur ve dosyaya iki satır metin yazar. Örnek daha sonra okumak için aynı dosyayı açar ve içerdiği metin satırlarını konsola kopyalar.
class Test { static void Main() { using (TextWriter w = File.CreateText("log.txt")) { w.WriteLine("This is line one"); w.WriteLine("This is line two"); } using (TextReader r = File.OpenText("log.txt")) { string s; while ((s = r.ReadLine()) != null) { Console.WriteLine(s); } } } }
TextWriterveTextReadersınıflarıIDisposablearayüzünü uyguladığı için, örnek, temel alınan dosyanın yazma veya okuma operasyonlarının ardından düzgün bir şekilde kapatılmasını sağlamak içinusingifadelerini kullanabilir.son örnek
uygulayan ResourceTypebir başvuru türü olduğundaIAsyncDisposable. Zaman uyumlu yöntemden zaman await using uyumsuz Dispose yönteme benzer değiştirmeler gerçekleştirmek için DisposeAsync diğer formülasyonlar.
await using Formun deyimi
await using (ResourceType resource = «expression» ) «statement»
, yerine yerine ile IAsyncDisposableIDisposableDisposeAsyncDispose aşağıda gösterilen formülasyonlara eşdeğerdir ve Task döndürülen DisposeAsync formülasyon ed'dir:await
await using (ResourceType resource = «expression» ) «statement»
ile eş değer
{
ResourceType resource = «expression»;
try
{
«statement»;
}
finally
{
IAsyncDisposable d = (IAsyncDisposable)resource;
if (d != null)
{
await d.DisposeAsync();
}
}
}
Not: embedded_statement tüm atlama deyimleri (§13.10) deyiminin
usinggenişletilmiş biçimine uygun olmalıdır. dipnot
13.14.2 Bildirimi kullanma
using deyiminin söz dizimsel bir değişkeni, using bildirimidir.
using_declaration
: 'await'? 'using' non_ref_local_variable_declaration ';' statement_list?
;
Using bildirimi aşağıdaki gibi aynı semantiklere sahiptir ve using deyiminin karşılık gelen kaynak alma biçimi (§13.14.1) ile yeniden yazılabilir:
using «local_variable_type» «local_variable_declarators»
// statements
ile eş değer
using («local_variable_type» «local_variable_declarators»)
{
// statements
}
and
await using «local_variable_type» «local_variable_declarators»
// statements
ile eş değer
await using («local_variable_type» «local_variable_declarators»)
{
// statements
}
Bir non_ref_local_variable_declaration bildirilen değişkenlerin ömrü, bildirildiği kapsamın sonuna kadar uzanır. Bu değişkenler daha sonra bildirildiği ters sırada atılır.
static void M()
{
using FileStream f1 = new FileStream(...);
using FileStream f2 = new FileStream(...), f3 = new FileStream(...);
...
// Dispose f3
// Dispose f2
// Dispose f1
}
Kullanma bildirimi doğrudan bir switch_label içinde gösterilmez, ancak bunun yerine bir switch_label içindeki bir blok içinde olabilir.
13.15 Ödeme tablosu
deyimi yield , bir yineleyicinin numaralandırıcı nesnesine (§15.15.5) veya numaralandırılabilir nesneye (§15.15.6) değer vermek veya yinelemenin sonuna işaret etmek için bir yineleyici bloğunda (§13.3) kullanılır.
yield_statement
: 'yield' 'return' expression ';'
| 'yield' 'break' ';'
;
yield bağlamsal bir anahtar sözcüktür (§6.4.4) ve yalnızca bir return veya break anahtar sözcüğün hemen öncesinde kullanıldığında özel bir anlamı vardır.
Aşağıda açıklandığı gibi bir yield deyimin nerede görünebileceğine ilişkin çeşitli kısıtlamalar vardır.
- Bir
yielddeyiminin (her iki biçimde de) bir method_body, operator_body veya accessor_body dışında görünmesi derleme zamanında hata oluşur. - Bir
yielddeyiminin (her iki biçimde de) anonim bir işlev içinde görünmesi, derleme zamanında bir hatadır. - Bir
yielddeyiminin (her iki biçimde de)finallykuralında görünmesitryderleme zamanı hatasıdır. -
yield returndeyiminin, herhangi birtryiçeren bir deyimi içinde herhangi bir yerde görünmesi derleme zamanı hatasıdır.
Örnek: Aşağıdaki örnekte deyimlerin
yieldbazı geçerli ve geçersiz kullanımları gösterilmektedir.delegate IEnumerable<int> D(); IEnumerator<int> GetEnumerator() { try { yield return 1; // Ok yield break; // Ok } finally { yield return 2; // Error, yield in finally yield break; // Error, yield in finally } try { yield return 3; // Error, yield return in try/catch yield break; // Ok } catch { yield return 4; // Error, yield return in try/catch yield break; // Ok } D d = delegate { yield return 5; // Error, yield in an anonymous function }; } int MyMethod() { yield return 1; // Error, wrong return type for an iterator block }son örnek
Deyimdeki ifadenin türünden yineleyicinin verim türüne (§15.15.4) örtük dönüştürme (§10.2) bulunacaktır.yield return
Bir yield return ifadesi aşağıdaki gibi yürütülür:
- deyiminde verilen ifade değerlendirilir, örtük olarak verim türüne dönüştürülür ve numaralandırıcı nesnesinin özelliğine
Currentatanır. - Yineleyici bloğunun yürütülmesi askıya alınır.
yield returndeyimi bir veya daha fazlatryblok içindeyse, ilişkilifinallybloklar şu anda yürütülmedi. -
MoveNextNumaralandırıcı nesnesinin yöntemi, numaralandırıcı nesnesinin sonraki öğeye başarıyla ilerlediğini belirterek çağırana geri dönertrue.
Numaralandırıcı nesnesinin MoveNext yöntemine yapılan sonraki çağrı, yineleyici bloğunun yürütülmesini en son askıya alındığı yerden sürdürür.
Bir yield break ifadesi aşağıdaki gibi yürütülür:
- Eğer
yield breakdeyimi, ilişkilitrybloklara sahip bir veya daha fazlafinallyblok tarafından içine alındıysa, kontrol başlangıçta en içtekifinallydeyimintrybloğuna aktarılır. Birfinallybloğunun bitiş noktasına ulaşıldığında ve bu gerçekleştiğinde, kontrol bir sonraki kapsayanfinallydeyiminintrybloğuna aktarılır. Bu işlem, tüm kapsayıcıfinallydeyimlerintryblokları yürütülene kadar yinelenir. - Yineleyici bloğunun denetimi, çağırana geri döndürülür. Bu, numaralandırıcı nesnesinin
MoveNextyöntemi veyaDisposeyöntemidir.
Bir yield break deyim, denetimi koşulsuz olarak başka bir yere aktardığından, deyiminin yield break bitiş noktasına hiçbir zaman ulaşılamaz.
ECMA C# draft specification