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 (§23.2) ve fixed_statement (§23.7) yalnızca güvenli olmayan kodda (§23) 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
if
ifadesi, dalında bir ifade yerine birif
gerektirdiğinden derleme zamanı hatasına sonuçlanır. Bu koda izin verilseydi değişkenii
bildirilir, 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.23) 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"); }
if
ifadesinin Boole ifadesi sabit bir ifadedir çünkü==
işlecin her iki işleneni de sabittir. Sabit ifade derleme zamanında değerlendirildiğinden,false
değeri üretilir veConsole.WriteLine
çağrısının ulaşılamaz olduğu kabul edilir. Ancak, yerel değişken olarak değiştirilirsei
void 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.WriteLine
ulaşılabilirliği aşağıdaki gibi belirlenir:
- Yöntemin bloğu ulaşılabilir olduğundan ilk
Console.WriteLine
ifade deyimineF
ulaşılabilir (§13.3).- İlk
Console.WriteLine
ifade deyiminin bitiş noktasına ulaşılabilir çünkü bu deyime ulaşılabilir (§13.7 ve §13.3).if
deyimine ulaşılabilir çünkü ilkConsole.WriteLine
ifade deyiminin bitiş noktasına ulaşılabilir (§13.7 ve §13.3).- İkinci
Console.WriteLine
ifade deyimi,if
deyiminin Boole ifadesi sabit bir değerfalse
iç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:
switch
deyimi 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 birbreak
deyiminin 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
return
deyiminin 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
return
deyiminin yineleyici bir blokta görünmesi bir derleme zamanı hatasıdır (ancakyield return
deyimlerine izin verilir). - Yineleyici bloğunun güvensiz bir bağlam içermesi, derleme zamanında bir hatadır (§23.2). 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
while
deyim 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
goto
blokları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ı
var
bir tür yoksa ve giriş implicitly_typed_local_variable_declaration eşleşiyorsa seçilir; - Aksi takdirde,
var
adı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: local_variable_declaration'ın for_initializer (§13.9.4) veya resource_acquisition (§13.14) olarak geçmediği durumlarda, bu soldan sağa sıra, ayrı bir local_variable_declaration içinde yer alan her bildirimciye 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 ref
variable_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 itself
son ö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
;
Açıkça belirtilmiş türde bir yerel değişken tanımı, belirtilen türe sahip bir veya birden fazla yerel değişken tanıtır.
Bir local_variable_initializer varsa, türü basit atama (§12.21.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şlatıcı variable_reference tür tür olmalı ve başvuru ataması (§12.21.3) için aynı gereksinimleri karşılamalıdır.
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.23) 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.
local_function_declaration bir async
(§15.14) değiştirici ve bir unsafe
(§23.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 (§23.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.x
olduğ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
this
vegoto
, §12.19.3'teki anonim işlevlerin kurallarını yansıtıyor. 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,
L
başlangıç noktası ulaşılabilir olmasa bileL
gövdesine ulaşılabilir.L
başlangıç noktasına ulaşılamadığı içinL
uç 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
this
başvurusundan veyabase
ya 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 + y
gibi 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
if
deyimiif (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.24) 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 deyimininif
bitiş noktasına aktarılır. - Boole ifadesi ortaya
false
çıkarsa ve birelse
parç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 deyimininif
bitiş noktasına aktarılır. - Boole ifadesi
false
sonucunu verirse ve birelse
kısım yoksa, denetimif
deyiminin 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 false
sahip 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
switch
deyimi, switch ifadesinin değerine karşılık gelen ilgili anahtar etiketine sahip bir deyim listesini yürütmek üzere seçer.
switch_statement
: 'switch' '(' expression ')' switch_block
;
switch_block
: '{' switch_section* '}'
;
switch_section
: switch_label+ statement_list
;
switch_label
: 'case' pattern case_guard? ':'
| 'default' ':'
;
case_guard
: 'when' expression
;
switch_statement, anahtar sözcüğünden switch
ve ardından parantezli ifadeden (anahtar ifadesi 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. Değeri test edilen her switch_label içeren case
, switch ifadesinin karşılaştırıldığı 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.
Deyimin switch ifadesi tarafından oluşturulur.
- Switch ifadesinin türü
sbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
,bool
,string
veya bir enum_type ise veya bu türlerden birine karşılık gelen null atanabilir değer türüyse, bu deyimin yöneten türdürswitch
. - Aksi takdirde, anahtar ifadelerinin türünden aşağıdaki olası yönetim türlerinden birine yönelik tam olarak bir kullanıcı tanımlı örtük dönüştürme varsa:
sbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
,string
veya bu türlerden birine karşılık gelen null atanabilir bir değer türü varsa, dönüştürülen tür,switch
ifadesinin yönetim türüdür. - Aksi takdirde,
switch
deyiminin yönlendiren türü, switch ifadesinin 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:
- Switch ifadesi değerlendirilir ve yöneten türe dönüştürülür.
- Denetim, dönüştürülen anahtar ifadesinin değerine göre aktarılır:
- Anahtar ifadesinin
case
değeriyle eşleşen ve koruma ifadesinin eksik olduğu veya true olarak değerlendirildiği aynıswitch
ifadedeki etiket kümesinin ilk deseni, denetimin eşleşencase
etiketi izleyen ifade listesine aktarılmasına neden olur. - Aksi takdirde, bir
default
etiketi varsa, kontroldefault
etiketinin ardından gelen deyim listesine aktarılır. - Aksi takdirde, kontrol
switch
ifadesinin bitiş noktasına aktarılır.
- Anahtar ifadesinin
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
true
olarak 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 case
veyagoto default
deyimi 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
switch
bö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 case
veyagoto default
deyimiyle biter, ancak deyim listesinin bitiş noktasını erişilemez hale getiren herhangi bir yapıya izin verilir. Örneğin, Boole ifadesi tarafından denetlenen birwhile
deyiminintrue
hiçbir zaman bitiş noktasına ulaşmadığı bilinmektedir. Benzer şekilde, birthrow
veyareturn
deyimi 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
switch
idare türü türüstring
olabilir. Ö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.12.8) gibi,
switch
deyimi de büyük/küçük harf duyarlıdır ve anahtar ifadesi dizesi bir etiket sabitiyle tam olarak eşleştiğinde belirli bircase
durum bölümünü yürütür. son not Birswitch
deyiminin idare türü veya null atanabilir bir değer türü olduğundastring
, değerenull
etiket sabiticase
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:
- Switch ifadesi 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
default
etikettir 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
- Switch ifadesi sabit bir değer değildir ve
- etiket,
case
değeri false sabiti olmayan, korumasız veya koruyucusu olmayan bir etikettir; veya - bu bir
default
etikettir 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,
null
ile eşleşecek bir desen içermez.
- etiket,
- Anahtar etiketi, erişilebilir bir
goto case
veyagoto default
deyimi 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.
-
switch
deyiminin içinde,break
deyiminden çıkan erişilebilir birswitch
deyimi vardır. - Ya hiç
default
etiketi yok veya- Anahtar ifadesi sabit olmayan bir değerdir ve değeri sabit true olan korumalar içermeyen veya bu tür korumalar barındıran switch deyimi durumları arasında yer alan desenlerin kümesi, anahtar kontrol türü için kapsamlı değildir (§11.4).
- Switch ifadesi, null atanabilir bir türün sabit olmayan bir değerdir ve true sabitine sahip korumalar veya korumaları olmayan switch ifadesi durumlarının hiçbirinde herhangi bir desen
null
ile uyuşmaz. - Switch ifadesi sabit bir değerdir ve korumasız veya koruyucusu true sabiti olan hiçbir
case
etiket bu değerle eşleşmez.
Örnek: Aşağıdaki kod, yan tümcesinin
when
kı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.24) değerlendirilir.
- Boole ifadesi
true
sonuç verirse, kontrol gömülü deyime aktarılır. Denetim, ekli deyimin bitiş noktasına ulaştığında ve eğer bu bircontinue
deyiminin yürütülmesinden kaynaklanıyorsa, denetimwhile
deyiminin başına aktarılır. - Boole ifadesi değerini verirse
false
, denetim deyimininwhile
bitiş 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:
-
while
deyiminin içinde,break
deyiminden çıkan erişilebilir birwhile
deyimi vardır. -
while
deyimine ulaşılabilir ve Boole ifadesi sabit değerinetrue
sahip 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 katıştırılmış deyimin bitiş noktasına ulaştığında (büyük olasılıkla bir
continue
deyimin yürütülmesinden), boolean_expression (§12.24) değerlendirilir. Boolean ifadesinin sonucutrue
ise, denetimdo
deyiminin başına aktarılır. Aksi takdirde, kontroldo
ifadesinin 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:
-
do
deyiminin içinde,break
deyiminden çıkan erişilebilir birdo
deyimi vardır. - Katıştırılmış deyiminin bitiş noktasına ulaşılabilir ve Boole ifadesi sabit değerine
true
sahip 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.
for_condition mevcutsa, bir boolean_expression (§12.24) 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 bircontinue
deyimin 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 deyimininfor
bitiş 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
for
ulaşılabilir ancak for_condition mevcut değil. -
for
deyimine 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:
-
for
deyiminin içinde,break
deyiminden çıkan erişilebilir birfor
deyimi vardır. -
for
deyimine 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ü, numaralandırıcı türünü ve yineleme türünü belirler. Bir foreach
deyiminin işlenmesi §13.9.5.2'de ve bir await foreach
deyimi için işleme süreci §13.9.5.3'te ayrıntılı olarak açıklanmıştır.
Not: İfade
null
değerine sahipse, çalışma zamanında birSystem.NullReferenceException
fırlatılır. dipnot
Bir uygulamanın belirli bir foreach_statement farklı şekilde uygulamasına izin verilir; örneğin, performans nedenleriyle, davranış yukarıdaki genişletmeyle tutarlı olduğu sürece.
13.9.5.2 Zaman uyumlu foreach
Bir foreach
deyiminin derleme zamanı işlemesi önce ifadenin koleksiyon türünü, numaralandırıcı türünü ve yineleme türünü belirler. Bu belirleme aşağıdaki gibi devam eder:
- Eğer
X
türü bir dizi türüyse, X'ten arabirimine örtük bir başvuru dönüşümü vardır (çünküIEnumerable
bu arabirimi uygular). Koleksiyon türü arabirim,IEnumerable
numaralandırıcı türüIEnumerator
arabirim ve yineleme türü ise dizi türünün öğe türüdürX
. - Eğer
X
türüdynamic
ise, o zaman ifadesi’denIEnumerable
arabirimine (§10.2.10) örtük bir dönüştürme vardır. Koleksiyon türüIEnumerable
arabirimi, numaralandırıcı türü iseIEnumerator
arabirimidir.var
Tanımlayıcı local_variable_type olarak verilirse yineleme türü olurdynamic
, aksi takdirde olurobject
. - Aksi takdirde, tür
X
'ın uygun birGetEnumerator
metodu olup olmadığını belirleyin.- Tür
X
üzerinde,GetEnumerator
tanımlayıcısıyla ve 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, aşağıda 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.
-
E
yönteminin dönüş türüGetEnumerator
bir sınıf, yapı veya arabirim türü değilse, bir hata oluşturulur ve başka adım atılmaz. - Üye arama,
E
üzerinde, tanımlayıcıCurrent
kullanılarak ve tür bağımsız değişkeni olmaksızın gerçekleştirilir. Üye araması eşleşme sağlamazsa veya sonuç, okumaya izin veren bir genel örnek özelliği dışında bir şeyse, bir hata oluşturulur ve başka bir adım atılmaz. - Üye arama,
E
üzerinde, tanımlayıcıMoveNext
kullanılarak ve tür bağımsız değişkeni olmaksızın gerçekleştirilir. Üye araması eşleşme üretmezse veya sonuç bir yöntem grubu dışında herhangi bir şey olursa, bir hata üretilir ve başka adım atılmaz. - Aşırı yükleme çözümlemesi, yöntem grubunda boş bir bağımsız değişken listesiyle gerçekleştirilir. Aşırı yükleme çözümlemesi geçerli bir yöntemle sonuçlanmazsa, belirsizlikle sonuçlanırsa veya tek bir en iyi yöntemle sonuçlanırsa, ancak bu yöntem statikse veya genel değilse ya da dönüş türü değilse
bool
, bir hata oluşturulur ve başka bir adım atılmaz. - Koleksiyon türü
X
, numaralandırıcı türüE
ve yineleme türüCurrent
özelliğinin türüdür.Current
özelliği değiştiriciyiref
içerebilir; bu durumda döndürülen ifade isteğe bağlı olarak salt okunur olan bir variable_reference (§9.5) olur.
- Tür
- Aksi takdirde, numaralandırılabilir bir arabirim olup olmadığını denetleyin:
-
Tᵢ
içinX
'den örtük dönüştürmenin olduğu tümIEnumerable<Tᵢ>
türleri arasında,T
T
olmadığı ve diğer tümdynamic
türleri içinTᵢ
'denIEnumerable<T>
'e örtük bir dönüştürme olduğu benzersiz bir türIEnumerable<Tᵢ>
varsa, koleksiyon türü arabirimiIEnumerable<T>
, numaralandırıcı türü arabirimiIEnumerator<T>
ve yineleme türüT
olur. - Aksi takdirde,
T
birden fazla tür varsa bir hata üretilir ve başka bir adım atılmaz. - Aksi takdirde,
X
'danSystem.Collections.IEnumerable
arabirimine örtük bir dönüştürme varsa, koleksiyon türü bu arabirimdir, numaralandırıcı türüSystem.Collections.IEnumerator
arabirimidir ve yineleme türüobject
olur. - Aksi takdirde bir hata oluşturulur ve başka bir adım atılmaz.
-
Yukarıdaki adımlar başarılı olursa, bir koleksiyon türü C
, numaralandırıcı türü E
ve yineleme türü T
, ref T
veya ref readonly T
oluşturur.
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. Referans değişkeni v
gömülü deyimde okuma-yazma iznine sahiptir, ancak v
yeniden ref ataması yapılmamalıdır (§12.21.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 v
içine yerleştirilmesi, while
içinde bulunan herhangi bir anonim işlev tarafından nasıl yakalandığı (§12.19.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
v
döngü dışında bildirilirse, tüm yinelemeler arasında paylaşılır vewhile
döngüsünden sonraki değeri, yani son değer, olur. Bu,for
çağrısının yazdıracağı13
değeridir. Bunun yerine, her yinelemenin kendi değişkeniv
olduğundan, ilk yinelemedef
tarafından yakalanan değer, yazdırılacak olan değeri7
tutmaya devam eder. (Önceki C# sürümlerindev
ifadesininwhile
dö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.IDisposable
arabirimine örtük bir dönüştürme varsa,E
null olamaz bir değer türüysefinally
yan tümcesi şu anlamsal eşdeğerine genişletilir:finally { ((System.IDisposable)e).Dispose(); }
Aksi takdirde,
finally
tümcesi aşağıdaki anlamsal eşdeğer hale genişletilir:finally { System.IDisposable d = e as System.IDisposable; if (d != null) { d.Dispose(); } }
E
bir 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
E
yanfinally
tümcesi boş bir bloğa genişletilir:finally {}
Aksi takdirde,
finally
yan 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 – 1
biten 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.9
son örnek
Örnek: Aşağıdaki örnekte
int[] numbers = { 1, 3, 5, 7, 9 }; foreach (var n in numbers) { Console.WriteLine(n); }
n
türünün,int
olduğu,numbers
'nın yineleme türü olarak tahmin edilir.son örnek
13.9.5.3 foreach bekleniyor
Bir foreach
deyiminin derleme zamanı işlemesi önce ifadenin koleksiyon türünü, numaralandırıcı türünü ve yineleme türünü belirler. Bir foreach
deyiminin işlenmesi §13.9.5.2'de ve bir await foreach
deyimi için işleme süreci §13.9.5.3'te ayrıntılı olarak açıklanmıştır.
Bu belirleme aşağıdaki gibi devam eder:
- Türün
X
uygunGetAsyncEnumerator
bir yöntemi olup olmadığını belirleyin:- Tür
X
üzerinde,GetAsyncEnumerator
tanımlayıcısıyla ve 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, aşağıda 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.
-
E
yönteminin dönüş türüGetAsyncEnumerator
bir sınıf, yapı veya arabirim türü değilse, bir hata oluşturulur ve başka adım atılmaz. - Üye arama,
E
üzerinde, tanımlayıcıCurrent
kullanılarak ve tür bağımsız değişkeni olmaksızın gerçekleştirilir. Üye araması eşleşme sağlamazsa veya sonuç, okumaya izin veren bir genel örnek özelliği dışında bir şeyse, bir hata oluşturulur ve başka bir adım atılmaz. - Üye arama,
E
üzerinde, tanımlayıcıMoveNextAsync
kullanılarak ve tür bağımsız değişkeni olmaksızın gerçekleştirilir. Üye araması eşleşme üretmezse veya sonuç bir yöntem grubu dışında herhangi bir şey olursa, bir hata üretilir ve başka adım atılmaz. - Aşırı yükleme çözümlemesi, yöntem grubunda boş bir bağımsız değişken listesiyle gerçekleştirilir. Aşırı yükleme çözümlemesi geçerli bir yöntemle sonuçlanmazsa, belirsizlikle sonuçlanırsa veya tek bir en iyi yöntemle sonuçlanırsa, ancak bu yöntem statiktir veya genel değildir ya da await_expression (§12.9.8.3) olarak
bool
sınıflandırıldığı dönüş türü beklenemez (§12.9.8.2), bir hata oluşturulur ve başka bir adım atılmaz. - Koleksiyon türü
X
, numaralandırıcı türüE
ve yineleme türüCurrent
özelliğinin türüdür.
- Tür
- Aksi takdirde, zaman uyumsuz bir numaralandırılabilir arabirim olup olmadığını denetleyin.
-
Tᵢ
içinX
'den örtük dönüştürmenin olduğu tümIAsyncEnumerable<Tᵢ>
türleri arasında,T
T
olmadığı ve diğer tümdynamic
türleri içinTᵢ
'denIAsyncEnumerable<T>
'e örtük bir dönüştürme olduğu benzersiz bir türIAsyncEnumerable<Tᵢ>
varsa, koleksiyon türü arabirimiIAsyncEnumerable<T>
, numaralandırıcı türü arabirimiIAsyncEnumerator<T>
ve yineleme türüT
olur. - Aksi takdirde,
T
birden fazla tür varsa bir hata üretilir ve başka bir adım atılmaz. - Aksi takdirde bir hata oluşturulur ve başka bir adım atılmaz.
-
Başarıyla gerçekleştirildiğinde yukarıdaki adımlar, açık bir şekilde C
koleksiyon türü, E
enumerator türü ve T
yineleme türü oluşturur.
await foreach
Formun deyimi
await foreach (V v in x) «embedded_statement»
daha sonra şu değerle eşdeğerdir:
{
E e = ((C)(x)).GetAsyncEnumerator();
try
{
while (await e.MoveNextAsync())
{
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 (await foreach
) yoksa, bir hata üretilir ve başka bir adım atılmaz.
Zaman uyumsuz bir numaralandırıcı, isteğe bağlı olarak bağımsız değişken almadan çağrılabilen ve döndürdüğünde DisposeAsync
edilebilen ve await
'sinin GetResult()
döndürdüğü bir void
yöntemini sunabilir.
foreach
biçiminde bir ifade
await foreach (T item in enumerable) «embedded_statement»
şu şekilde genişletilir:
var enumerator = enumerable.GetAsyncEnumerator();
try
{
while (await enumerator.MoveNextAsync())
{
T item = enumerator.Current;
«embedded_statement»
}
}
finally
{
await enumerator.DisposeAsync(); // omitted, along with the try/finally,
// if the enumerator doesn't expose DisposeAsync
}
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"); } }
finally
ikitry
deyimle 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 break
son ö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
, , while
do
, for
veya 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
, , for
veya 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
break
deyimi, ilişkilitry
bloklarla bir veya daha fazlafinally
bloktan çıkarsa, denetim başlangıçta en içtekifinally
deyiminintry
bloğuna aktarılır. Birfinally
bloğunun bitiş noktasına ulaşıldığında ve bu gerçekleştiğinde, kontrol bir sonraki kapsayanfinally
deyiminintry
bloğuna aktarılır. Bu işlem, tüm araya gelenfinally
ifadelerintry
blokları yürütülene kadar yinelenir. - Denetim,
break
deyiminin 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
, for
veya 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
continue
deyimi, ilişkilitry
bloklarla bir veya daha fazlafinally
bloktan çıkarsa, denetim başlangıçta en içtekifinally
deyiminintry
bloğuna aktarılır. Birfinally
bloğunun bitiş noktasına ulaşıldığında ve bu gerçekleştiğinde, kontrol bir sonraki kapsayanfinally
deyiminintry
bloğuna aktarılır. Bu işlem, tüm araya gelenfinally
ifadelerintry
blokları yürütülene kadar yinelenir. - Denetim,
continue
deyiminin 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
goto
denetimi 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
goto
ifadeyi 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
goto
deyimi, ilişkilitry
bloklarla bir veya daha fazlafinally
bloktan çıkarsa, denetim başlangıçta en içtekifinally
deyiminintry
bloğuna aktarılır. Birfinally
bloğunun bitiş noktasına ulaşıldığında ve bu gerçekleştiğinde, kontrol bir sonraki kapsayanfinally
deyiminintry
bloğuna aktarılır. Bu işlem, tüm araya gelenfinally
ifadelerintry
blokları yürütülene kadar yinelenir. - Denetim,
goto
deyiminin 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; ref
ifade 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 void
sahip 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.19) 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üşü
readonly
içeriyorsa, sonuçta elde edilen değişken salt okunurdur. - Deyim, bir veya daha fazla
return
veyatry
blokla birlikte ilişkilicatch
blokların içine alınmışsa, denetim başlangıçta en içtekifinally
deyiminfinally
bloğuna aktarılır. Birfinally
bloğunun bitiş noktasına ulaşıldığında ve bu gerçekleştiğinde, kontrol bir sonraki kapsayanfinally
deyiminintry
bloğuna aktarılır. Bu işlem, tüm kapsayıcıfinally
deyimlerintry
blokları 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ış (§21.4) içinde belirtilir.
Geçerli fonksiyon üyesinde, atılan noktayı kapsayan her
try
deyim incelenir. Her bir ifadeS
için, en içtekitry
ifadeden başlayarak en dıştakitry
ifadeye kadar, aşağıdaki adımlar değerlendirilir:- Eğer
try
bloğuS
, atma noktasını kapatıyorsa veS
bir veya daha fazlacatch
yan tümcesine sahipse,catch
yan 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 ilkT
yan 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. Bircatch
yan tümce bir özel durum filtresi içerdiğinde, eğer bu özel durum filtresicatch
olarak değerlendirilirse, butrue
yan 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şencatch
bir yan tümce bulunursa, denetimi bucatch
yan tümcenin bloğuna aktararak özel durum yayma işlemi tamamlanır. - Aksi takdirde,
try
bloğu veya bircatch
bloğuS
atma noktasını kapatıyorsa veS
'ün birfinally
bloğu varsa, denetimfinally
bloğuna aktarılır.finally
Blok başka bir özel durum oluşturursa geçerli özel durumun işlenmesi sonlandırılır. Aksi takdirde, denetim bloğunfinally
bitiş 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.Exception
tü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 genelcatch
bir ifade kullanılabilir. Bu nedenle, genel bircatch
yan tümce, türünüSystem.Exception
belirten 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
catch
koş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
F
bir ö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: G
Eğer ilk
catch
blok, geçerli özel durumu yeniden fırlatmak yerinee
fırlatsaydı, üretilen çıkış şöyle olurdu:Exception in F: G Exception in Main: F
son örnek
break
, continue
veya goto
deyiminin, bir finally
bloğunun dışına denetimi aktarması derleme zamanı hatasıdır. Bir break
, continue
veya 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 ö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
, continue
veya deyiminin yürütülmesinin goto
sonucu 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
Method
bir özel durum oluşturur. İlk eylem, kapsayıcıcatch
yan tümceleri inceleyerek ve herhangi bir özel durum filtresi yürütmektir. Ardından,finally
içindekiMethod
yan tümcesi, kontrol kapsayan eşleşencatch
yan tümceye aktarılmadan önce yürütülür. Sonuçta elde edilen çıktı:Filter Finally Catch
son ö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
try
bitiş noktasına ulaşılabilir veya en az bircatch
bloğun bitiş noktasına ulaşılabilir. - Bir
finally
blok varsa bloğunfinally
bitiş 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
using
deyimi, bir veya daha fazla kaynağı alır, bir deyimi yürütür ve ardından kaynakları atar.
using_statement
: 'using' '(' resource_acquisition ')' embedded_statement
;
resource_acquisition
: local_variable_declaration
| expression
;
A kaynak, zaman uyumsuz akışlar için System.IDisposable
ve diğer durumlar için IAsyncDisposable
arabirimini uygulayan ve zaman uyumsuz akışlar için Dispose
ve diğer durumlar için DisposeAsync
adında tek bir parametresiz yöntemi içeren bir sınıf veya yapıdır. Kaynak kullanan kod, kaynağın artık gerekli olmadığını belirtmek için çağrısı Dispose
yapabilir.
resource_acquisition biçimi local_variable_declaration ise local_variable_declaration türü ya dynamic
ya da System.IDisposable
'e örtük olarak dönüştürülebilen bir tür olmalıdır (IAsyncDisposable
zaman uyumsuz akışlar için).
resource_acquisition biçimi ifade ise, bu ifade örtük olarak System.IDisposable
olarak dönüştürülebilir olmalıdır (IAsyncDisposable
zaman uyumsuz akışlar için).
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. Eğer bir null
kaynak alınırsa, Dispose
çağrısı yapılmaz (DisposeAsync
zaman uyumsuz akışlar için) ve özel durum atılmaz. Kaynak türü dynamic
ise, dönüştürmenin kullanım ve elden çıkarma işleminden önce başarılı olduğundan emin olmak için edinim sırasında (IDisposable
zaman uyumsuz akışlar için) şeklinde örtük dinamik dönüşüm (IAsyncDisposable
) yoluyla dinamik olarak dönüştürülür.
using
biçiminde bir ifade
using (ResourceType resource = «expression» ) «statement»
üç olası genişletmeden birine karşılık gelir. Null değer atanamayan bir değer türü veya değer türü kısıtlamasına (ResourceType
) sahip bir tür parametresi olduğunda, genişletme anlamsal olarak 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, ResourceType
dynamic
olduğunda, genişleme
{
ResourceType resource = «expression»;
IDisposable d = resource;
try
{
«statement»;
}
finally
{
if (d != null)
{
d.Dispose();
}
}
}
Aksi takdirde, genişleme şöyledir:
{
ResourceType resource = «expression»;
try
{
«statement»;
}
finally
{
IDisposable d = (IDisposable)resource;
if (d != null)
{
d.Dispose();
}
}
}
Herhangi bir genişletmede, katıştırılmış deyimdeki resource
değişkeni salt okunurdur ve d
değişkenine erişilemez ve bu deyimde görünmez.
Bir uygulamanın, davranış yukarıdaki genişletmeyle tutarlı olduğu sürece performans nedenleriyle belirli bir using_statement farklı bir şekilde uygulamasına izin verilir.
using
yapısında bir ifade:
using («expression») «statement»
aynı üç olası genişletmeye sahiptir. Bu durumda, ResourceType
derleme zamanı türü, eğer varsa, ile örtük olarak belirlenir. Aksi takdirde, arabirimin kendisi IDisposable
(IAsyncDisposable
asenkron akışlar için) ResourceType
olarak kullanılır.
resource
değişkenine erişilemez ve ekli deyimde görünmez.
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); } } } }
TextWriter
veTextReader
sınıflarıIDisposable
arayü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çinusing
ifadelerini kullanabilir.son örnek
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
yield
deyiminin (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
yield
deyiminin (her iki biçimde de) anonim bir işlev içinde görünmesi, derleme zamanında bir hatadır. - Bir
yield
deyiminin (her iki biçimde de)finally
kuralında görünmesitry
derleme zamanı hatasıdır. -
yield return
deyiminin, herhangi birtry
içeren bir deyimi içinde herhangi bir yerde görünmesi derleme zamanı hatasıdır.
Örnek: Aşağıdaki örnekte deyimlerin
yield
bazı 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
Current
atanır. - Yineleyici bloğunun yürütülmesi askıya alınır.
yield return
deyimi bir veya daha fazlatry
blok içindeyse, ilişkilifinally
bloklar şu anda yürütülmedi. -
MoveNext
Numaralandı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 break
deyimi, ilişkilitry
bloklara sahip bir veya daha fazlafinally
blok tarafından içine alındıysa, kontrol başlangıçta en içtekifinally
deyimintry
bloğuna aktarılır. Birfinally
bloğunun bitiş noktasına ulaşıldığında ve bu gerçekleştiğinde, kontrol bir sonraki kapsayanfinally
deyiminintry
bloğuna aktarılır. Bu işlem, tüm kapsayıcıfinally
deyimlerintry
blokları yürütülene kadar yinelenir. - Yineleyici bloğunun denetimi, çağırana geri döndürülür. Bu, numaralandırıcı nesnesinin
MoveNext
yöntemi veyaDispose
yö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