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.
7.1 Uygulama başlatma
Bir program, diğer uygulamaların parçası olarak kullanılacak bir sınıf kitaplığı olarak veya doğrudan başlatılmış bir uygulama olarak derlenebilir. Bu derleme modunu belirleme mekanizması uygulama tanımlıdır ve bu belirtim dışındadır.
Uygulama olarak derlenen bir program, aşağıdaki gereksinimleri karşılayarak giriş noktası olarak nitelenen en az bir yöntem içermelidir:
- İsmi
Main
olacaktır. - Şöyle olacaktır
static
. - Genel olmayacak.
- Bildirim, genel olmayan bir türde yapılmalıdır. Yöntemi belirten tür iç içe bir türse, kapsayan türlerin hiçbiri genel olmayabilir.
- Yöntemin dönüş türü
async
veyaSystem.Threading.Tasks.Task
olduğundaSystem.Threading.Tasks.Task<int>
değiştiricisine sahip olabilir. - Dönüş türü , ,
void
int
veyaSystem.Threading.Tasks.Task
olmalıdırSystem.Threading.Tasks.Task<int>
. - Uygulama yapılmadan kısmi bir yöntem (§15.6.9) olmamalıdır.
- Parametre listesi boş olmalı veya türünde
string[]
tek bir değer parametresine sahip olmalıdır.
Not: Değiştiriciye sahip yöntemlerin
async
giriş noktası olarak nitelenebilmesi için yukarıda belirtilen iki dönüş türünden tam olarak birine sahip olması gerekir. Birasync void
yöntem veya farklı bir beklenebilir tür döndüren,async
veyaValueTask
gibi birValueTask<int>
yöntemi giriş noktası olarak nitelenmez. dipnot
Bir program içinde giriş noktası olarak nitelenen birden fazla yöntem bildirilirse, uygulamanın gerçek giriş noktası olarak kabul edilen yöntemi belirtmek için bir dış mekanizma kullanılabilir.
int
veya void
dönüş türüne sahip bir uygun yöntem bulunursa, System.Threading.Tasks.Task
veya System.Threading.Tasks.Task<int>
dönüş türüne sahip herhangi bir uygun yöntem giriş noktası yöntemi olarak kabul edilmez. Bir programın tam olarak bir giriş noktası olmadan uygulama olarak derlenmiş olması derleme zamanı hatasıdır. Sınıf kitaplığı olarak derlenen bir program, uygulama giriş noktası olarak nitelenecek yöntemler içerebilir, ancak sonuçta elde edilen kitaplığın giriş noktası yoktur.
Normalde, bir yöntemin bildirilen erişilebilirliği (§7.5.2), bildiriminde belirtilen erişim değiştiricileri (§15.3.6) tarafından belirlenir ve benzer şekilde bir türün bildirilen erişilebilirliği, bildiriminde belirtilen erişim değiştiricileri tarafından belirlenir. Belirli bir türdeki belirli bir yöntemin çağrılabilmesi için hem türün hem de üyenin erişilebilir olması gerekir. Ancak, uygulama giriş noktası özel bir durumdur. Özellikle, yürütme ortamı, uygulamanın giriş noktasına bildirilen erişilebilirliği ne olursa olsun ve kapsayan tür bildirimlerinin bildirilen erişilebilirliği ne olursa olsun erişebilir.
Giriş noktası yönteminin dönüş türü System.Threading.Tasks.Task
veya System.Threading.Tasks.Task<int>
olduğunda, derleyici karşılık gelen Main
yöntemini çağıran zaman uyumlu bir giriş noktası yöntemini sentezleyecektir.
Main
yöntemine dayalı olarak, sentezlenen yöntemin parametreleri ve dönüş türleri vardır.
- Sentezlenen yöntemin parametre listesi, yöntemin parametre listesiyle
Main
aynıdır - Yöntemin
Main
dönüş türü iseSystem.Threading.Tasks.Task
, sentezlenen yöntemin dönüş türü şudur:void
- Yöntemin
Main
dönüş türü iseSystem.Threading.Tasks.Task<int>
, sentezlenen yöntemin dönüş türü şudur:int
Sentezlenen yöntemin yürütülmesi aşağıdaki gibi devam eder:
- Sentezlenen yöntem, eğer
Main
yönteminin böyle bir parametresi varsa,string[]
parametre değerini bağımsız değişken olarak geçirecek şekildeMain
yöntemini çağırır. -
Main
Yöntem bir özel durum oluşturursa, bu özel durum oluşturulan yöntem tarafından yayılır. - Aksi takdirde, sentezlenen giriş noktası döndürülen görevin tamamlanmasını bekler ve parametresiz örnek yöntemini veya §C.3 ile belirtilen uzantı yöntemini kullanarak görevi
GetAwaiter().GetResult()
olarak çağırır. Görev başarısız olursa,GetResult()
bir özel durumu fırlatır ve bu özel durum sentezlenen method tarafından aktarılır. - Bir
Main
yöntemi için, dönüş türüSystem.Threading.Tasks.Task<int>
olan görev başarıyla tamamlanırsa,int
tarafından döndürülenGetResult()
değeri sentezlenmiş yöntemden döndürülür.
Bir uygulamanın etkili giriş noktası , program içinde bildirilen giriş noktasıdır veya yukarıda açıklandığı gibi bir giriş noktası gerekiyorsa sentezlenen yöntemdir. Bu nedenle, etkin giriş noktasının dönüş türü her zaman void
veya int
şeklindedir.
Bir uygulama çalıştırıldığında yeni bir uygulama etki alanı oluşturulur. Bir uygulamanın birkaç farklı örneklemesi aynı makinede aynı anda bulunabilir ve her birinin kendi uygulama etki alanı vardır. Uygulama etki alanı, uygulama durumu için kapsayıcı görevi yaparak uygulama yalıtımını etkinleştirir. Uygulama etki alanı, uygulamada tanımlanan türler ve kullandığı sınıf kitaplıkları için kapsayıcı ve sınır işlevi görür. Bir uygulama etki alanına yüklenen türler, başka bir uygulama etki alanına yüklenen aynı türlerden farklıdır ve nesne örnekleri uygulama etki alanları arasında doğrudan paylaşılmaz. Örneğin, her uygulama etki alanı bu türler için kendi statik değişkenleri kopyasına sahiptir ve bir tür için statik oluşturucu, uygulama etki alanı başına en fazla bir kez çalıştırılır. Uygulamalar, uygulama etki alanlarının oluşturulmasına ve yok edilmesine yönelik uygulama tanımlı ilke veya mekanizmalar sağlamakta serbesttir.
Uygulama başlatma, yürütme ortamı uygulamanın etkili giriş noktasını çağırdığında gerçekleşir. Etkin giriş noktası bir parametre bildirirse, uygulama başlatılırken uygulama bu parametrenin ilk değerinin bir dize dizisine null olmayan bir başvuru olduğundan emin olacaktır. Bu dizi, uygulama başlatılmadan önce konak ortamı tarafından tanımlanan değerler verilen uygulama parametreleri olarak adlandırılan dizelere yönelik boş olmayan başvurulardan oluşacaktır. Amaç, barındırılan ortamın başka bir yerinden uygulama başlatmadan önce belirlenen uygulama bilgilerini sağlamaktır.
Not: Bir komut satırını destekleyen sistemlerde, uygulama parametreleri genellikle komut satırı bağımsız değişkenleri olarak bilinen öğelere karşılık gelir. dipnot
Geçerli giriş noktasının dönüş türü ise int
, uygulama sonlandırmada (§7.2) yürütme ortamı tarafından yöntem çağrısından döndürülen değer kullanılır.
Yukarıda listelenen durumlar dışında, giriş noktası yöntemleri her açıdan giriş noktası olmayan yöntemler gibi davranır. Özellikle, giriş noktası fonksiyonu uygulamanın ömrü boyunca normal yöntem çağrısı gibi başka bir noktada çağrılırsa, yöntem için özel bir işlem yapılmaz: Eğer bir parametre varsa, ilk değeri null
olabilir veya null başvurular içeren bir diziye başvuran bir null
olmayan değer olabilir. Benzer şekilde, giriş noktasının dönüş değerinin yürütme ortamından çağırma dışında özel bir önemi yoktur.
7.2 Uygulama sonlandırma
Uygulama sonlandırma , denetimi yürütme ortamına döndürür.
Uygulamanın etkili giriş noktası yönteminin dönüş türü ise int
ve yürütme bir özel durumla sonuçlanmadan tamamlanırsa, döndürülen değeri int
uygulamanın sonlandırma durum kodu işlevi görür. Bu kodun amacı, yürütme ortamıyla başarılı veya başarısız iletişimine izin vermektir. Etkin giriş noktası yönteminin dönüş türü ise void
ve yürütme bir özel durumla sonuçlanmadan tamamlanırsa sonlandırma durum kodu olur 0
.
Geçerli giriş noktası yöntemi bir özel durum (§21.4) nedeniyle sonlandırılırsa çıkış kodu uygulama tanımlıdır. Ayrıca, uygulama çıkış kodunu belirtmek için alternatif API'ler sağlayabilir.
Sonlandırıcıların (§15.13) uygulama sonlandırma kapsamında çalıştırılıp çalıştırılmayacağı uygulama tanımlıdır.
Not: .NET Framework uygulaması, temizleme işlemi (örneğin, kütüphane yöntemine yapılan bir çağrıyla) engellenmediği sürece henüz bellekten atılmamış tüm nesneler için sonlandırıcıları (
GC.SuppressFinalize
) çağırmak için her türlü makul çabayı gösterir. dipnot
7.3 Bildirimler
C# programındaki bildirimler, programın bileşen öğelerini tanımlar. C# programları ad alanları kullanılarak düzenlenir. Bunlar, tür bildirimleri ve iç içe ad alanı bildirimleri içerebilen ad alanı bildirimleri (§14) kullanılarak tanıtılır. Tür bildirimleri (§14.7), sınıfları (§15), yapıları (§16), arabirimleri (§18), numaralandırmaları (§19) ve temsilcileri (§20) tanımlamak için kullanılır. Tür bildiriminde izin verilen üye türleri, tür bildiriminin biçimine bağlıdır. Örneğin, sınıf bildirimleri sabitler (§15.4), alanlar (§15.5), yöntemler (§15.6), özellikler (§15.7), olaylar (§15.8), indeksleyiciler (§15.9), işleçler (§15.10), örnek oluşturucuları (§15.11), statik oluşturucular (§15.12), sonlandırıcılar (§15.13) ve iç içe türler (§15.3.9) için bildirimler içerebilir.
Bildirim, bildirimin ait olduğu bildirim alanında bir ad tanımlar. Aşağıdaki durumlar dışında, bir bildirim alanında aynı ada sahip üyeler içeren iki veya daha fazla bildirim olması derleme zamanında bir hatadır.
- Aynı bildirim alanında aynı ada sahip iki veya daha fazla ad alanı bildirimi izne açıktır. Bu tür ad alanı bildirimleri tek bir mantıksal ad alanı oluşturmak ve tek bir bildirim alanını paylaşmak için toplanır.
- Ayrı programlardaki ancak aynı ad alanı bildirim alanında yer alan bildirimlerin aynı adı paylaşmasına izin verilir.
Not: Ancak, bu bildirimler aynı uygulamaya dahil edilmişse belirsizliklere neden olabilir. dipnot
- Aynı ada sahip ancak ayrı imzalara sahip iki veya daha fazla yönteme aynı bildirim alanında izin verilir (§7.6).
- Aynı ada sahip iki veya daha fazla tür bildirimi, aynı bildirim alanında (§7.8.2), farklı sayıda tür parametresine sahip olabilir.
- Aynı bildirim alanında kısmi değiştiricisi olan iki veya daha fazla tür bildirimi aynı adı, aynı sayıda tür parametresini ve aynı sınıflandırmayı (sınıf, yapı veya arabirim) paylaşabilir. Bu durumda, tür bildirimleri tek bir türe katkıda bulunur ve tek bir bildirim alanı oluşturmak için toplanır (§15.2.7).
- Ad alanı bildirimi ve aynı bildirim alanında bir tür bildirimi, tür bildiriminde en az bir tür parametresi (§7.8.2) olduğu sürece aynı adı paylaşabilir.
Aşağıda açıklandığı gibi birkaç farklı bildirim alanı türü vardır.
- Bir programın tüm derleme birimlerinde, kapsayan bir namespace_declaration olmadan namespace_member_declaration olan bildirimler, genel bildirim alanı olarak adlandırılan tek bir birleşik bildirim alanının üyeleridir.
- Bir programın tüm derleme birimlerinde, aynı tam ad alanı adına sahip namespace_declaration içindeki namespace_member_declarationlar, tek birleştirilmiş bildirim alanının üyeleridir.
- Her bir compilation_unit ve namespace_body bir takma ad bildirim alanı vardır. extern_alias_directive ve using_alias_directive içeren her compilation_unit veya namespace_body, diğer ad bildirim alanına (§14.5.2) bir üye katkıda bulunur.
- Kısmi olmayan her sınıf, yapı veya arabirim bildirimi yeni bir bildirim alanı oluşturur. Her kısmi sınıf, yapı veya arabirim bildirimi, aynı programdaki tüm eşleşen parçalar tarafından paylaşılan bir bildirim alanına katkıda bulunur (§16.2.4). Bu bildirim alanına adlar class_member_declaration, struct_member_declaration, interface_member_declaration veya type_parameter aracılığıyla eklenir. Aşırı yüklenmiş örnek oluşturucu bildirimleri ve statik oluşturucu bildirimleri dışında, bir sınıf veya yapı, sınıf veya yapıyla aynı ada sahip bir üye bildirimi içeremez. Sınıf, yapı veya arabirim, aşırı yüklenmiş yöntemlerin ve dizin oluşturucuların bildirimine izin verir. Ayrıca, bir sınıf veya yapı aşırı yüklenmiş örnek oluşturucularının ve işleçlerinin bildirimine izin verir. Örneğin, bir sınıf, yapı veya arabirim, bu yöntem bildirimlerinin imzalarında farklılık göstermeleri koşuluyla aynı ada sahip birden çok yöntem bildirimi içerebilir (§7.6). Temel sınıfların bir sınıfın bildirim alanına katkıda bulunmadığını ve temel arabirimlerin bir arabirimin bildirim alanına katkıda bulunmadığını unutmayın. Bu nedenle, türetilmiş bir sınıf veya arabirimin devralınan üyeyle aynı ada sahip bir üyeyi bildirmesine izin verilir. Böyle bir üyenin devralınan üyeyi gizley dediği söylenir.
- Her temsilci bildirimi yeni bir bildirim alanı oluşturur. Adlar, parametreler (fixed_parameter s ve parameter_array) ve type_parameters aracılığıyla bu bildirim alanına eklenir.
- Her numaralandırma bildirimi yeni bir bildirim alanı oluşturur. Adlar, enum_member_declarations aracılığıyla bu bildirim alanına eklenir.
- Her yöntem bildirimi, özellik bildirimi, özellik erişimcisi bildirimi, dizin oluşturucu bildirimi, dizin oluşturucu erişimci bildirimi, işleç bildirimi, örnek oluşturucu bildirimi, anonim işlev ve yerel işlev, yerel değişken bildirim alanı olarak adlandırılan yeni bir bildirim alanı oluşturur. Adlar, parametreler (fixed_parameter s ve parameter_array) ve type_parameters aracılığıyla bu bildirim alanına eklenir. Bir özellik veya dizin oluşturucu için küme erişimcisi adı
value
parametre olarak tanıtır. İşlev üyesinin, anonim işlevin veya varsa yerel işlevin gövdesinin yerel değişken bildirim alanı içinde iç içe yerleştirilmiş olduğu kabul edilir. Yerel değişken tanımlama alanı ve iç içe geçmiş yerel değişken tanımlama alanı aynı ada sahip öğeler içerdiğinde, iç içe geçmiş yerel ad kapsamında, dış yerel ad iç içe geçmiş yerel ad tarafından gizlenir (§7.7.1). - Üye bildirimleri, anonim işlevler ve yerel işlevler içinde ek yerel değişken bildirim alanları oluşabilir. Adlar, patternlar, declaration_expressionlar, declaration_statementler ve exception_specifierler ile bu bildirim alanlarına eklenir. Yerel değişken bildirim alanları iç içe yerleştirilmiş olabilir, ancak yerel değişken bildirim alanı ve iç içe yerel değişken bildirim alanının aynı ada sahip öğeleri içermesi hatadır. Bu nedenle, iç içe bir bildirim alanında, kapsayan bir bildirim alanındaki bir parametre, tür parametresi, yerel değişken, yerel işlev veya sabit ile aynı ada sahip bir yerel değişken, yerel işlev veya sabiti bildirmek mümkün değildir. İki bildirim alanının da diğerini içermediği sürece, iki bildirim alanının aynı ada sahip öğeleri içermesi mümkündür. Yerel bildirim alanları aşağıdaki yapılar tarafından oluşturulur:
- Alan ve özellik bildirimindeki her variable_initializer kendi yerel değişken bildirim alanını tanıtır, bu alan başka hiçbir yerel değişken bildirim alanı içinde yer almaz.
- İşlev üyesinin, anonim işlevin veya varsa yerel işlevin gövdesi, işlevin yerel değişken bildirim alanına iç içe yerleştirilmiş olarak kabul edilen bir yerel değişken bildirim alanı oluşturur.
- Her constructor_initializer , örnek oluşturucu bildirimi içinde iç içe yerleştirilmiş bir yerel değişken bildirim alanı oluşturur. Oluşturucu gövdesinin yerel değişken bildirim alanı, bu yerel değişken bildirim alanı içinde iç içe yerleştirilmiştir.
- Her bir blok, switch_block, specific_catch_clause, iteration_statement ve using_statement, iç içe yerel değişken bildirim alanları oluşturur.
- Doğrudan bir ifadeler_listesinin parçası olmayan her gömülü_beyan iç içe geçmiş bir yerel değişken bildirim alanı oluşturur.
- Her switch_section iç içe yerel değişken bildirim alanı oluşturur. Ancak, doğrudan statement_list içindeki switch_section'de bildirilen değişkenler (ancak statement_list içindeki iç içe yerel değişken bildirim alanı içinde olmayanlar), switch_section yerine kapsayan switch_block'un yerel değişken bildirim alanına doğrudan eklenir.
- Bir query_expression (§12.20.3) söz dizimsel çevirisi bir veya daha fazla lambda ifadesi sunabilir. Anonim işlevler olarak, bunların her biri yukarıda açıklandığı gibi bir yerel değişken bildirim alanı oluşturur.
- Her blok veya switch_block etiketler için ayrı bir bildirim alanı oluşturur. Adlar labeled_statement s aracılığıyla bu bildirim alanına eklenir ve adlara goto_statementaracılığıyla başvurulur. Bir bloğun etiket bildirim alanı , iç içe blokları içerir. Bu nedenle, iç içe yerleştirilmiş bir bloğun içinde, kapsayan bir bloktaki etiketle aynı ada sahip bir etiket bildirmek mümkün değildir.
Not: Doğrudan bir switch_section içinde bildirilen değişkenlerin switch_section yerine switch_block yerel değişken bildirim alanına eklenmesi, şaşırtıcı bir koda yol açabilir. Aşağıdaki örnekte, durum 0 için switch bölümünde yer alan bildirime rağmen, yerel değişken
y
varsayılan durum için switch bölümünün kapsamı içindedir. Yerel değişkenz
, bildirimin gerçekleştiği switch bölümü için yerel değişken bildirim alanına eklendiğinden, varsayılan durum için switch bölümünde kapsam içinde değildir.int x = 1; switch (x) { case 0: int y; break; case var z when z < 10: break; default: y = 10; // Valid: y is in scope Console.WriteLine(x + y); // Invalid: z is not scope Console.WriteLine(x + z); break; }
dipnot
Adların bildirildiği metin sırası genel olarak anlamlı değildir. Özellikle, ad alanlarının, sabitlerin, yöntemlerin, özelliklerin, olayların, dizin oluşturucuların, işleçlerin, örnek oluşturucularının, sonlandırıcıların, statik oluşturucuların ve türlerin bildirimi ve kullanımı için metin düzeni önemli değildir. Bildirim sırası aşağıdaki şekillerde önemlidir:
- Alan bildirimleri için bildirim sırası, başlatıcılarının (varsa) yürütüleceği sırayı belirler (§15.5.6.2, §15.5.6.3).
- Yerel değişkenler kullanılmadan önce tanımlanmalıdır (§7.7).
- Constant_expression değerleri atlandığında enum üye bildirimlerinin bildirim sırası (§19.4) önemlidir.
Örnek: Bir ad alanının bildirim alanı "açık uçlu" ve aynı tam ada sahip iki ad alanı bildirimi aynı bildirim alanına katkıda bulunur. Örneğin:
namespace Megacorp.Data { class Customer { ... } } namespace Megacorp.Data { class Order { ... } }
Yukarıdaki iki ad alanı bildirimi, aynı bildirim alanına katkıda bulunur ve bu durumda tam nitelikli adlarına sahip
Megacorp.Data.Customer
veMegacorp.Data.Order
olmak üzere iki sınıf bildirir. İki bildirim aynı bildirim alanına katkıda bulunduğundan, her biri aynı ada sahip bir sınıfın bildirimini içeriyorsa derleme zamanı hatasına neden olur.son örnek
Not: Yukarıda belirtildiği gibi, bir bloğun bildirim alanı iç içe blokları içerir. Bu nedenle, aşağıdaki örnekte
F
veG
yöntemleri, adi
dış blokta bildirildiği ve iç blokta yeniden bildirilemeyeceği için bir derleme-zamanı hatasına neden olur. Ancak,H
veI
yöntemleri geçerlidir çünkü ikii
ayrı ve iç içe olmayan bloklarda bildirilmiştir.class A { void F() { int i = 0; if (true) { int i = 1; } } void G() { if (true) { int i = 0; } int i = 1; } void H() { if (true) { int i = 0; } if (true) { int i = 1; } } void I() { for (int i = 0; i < 10; i++) { H(); } for (int i = 0; i < 10; i++) { H(); } } }
dipnot
7.4 Üyeler
7.4.1 Genel
Ad alanlarının ve türlerin üyeleri vardır.
Not: Bir varlığın üyeleri genellikle varlığa başvuruyla başlayan ve ardından "
.
" belirteci ve ardından üyenin adıyla başlayan bir nitelenmiş ad kullanarak kullanılabilir. dipnot
Bir türün üyeleri tür bildiriminde bildirilir veya türün temel sınıfından devralınır. Bir tür bir temel sınıftan devraldığında, örnek oluşturucuları, sonlandırıcılar ve statik oluşturucular dışında temel sınıfın tüm üyeleri türetilmiş türün üyesi olur. Bir temel sınıf üyesinin bildirilen erişilebilirliği, üyenin devralınıp devralınmadığını denetlemez; devralma, örnek oluşturucu, statik oluşturucu veya sonlandırıcı olmayan herhangi bir üyeye genişletilir.
Not: Bununla birlikte, devralınan bir üyeye türetilmiş bir türde erişilemez, örneğin bildirilen erişilebilirliği (§7.5.2) nedeniyle. dipnot
7.4.2 Ad alanı üyeleri
Kapsayan ad alanı olmayan ad alanları ve türler genel ad alanının üyeleridir. Bu, doğrudan genel bildirim alanında bildirilen adlara karşılık gelir.
Ad alanı içinde bildirilen ad alanları ve türler bu ad alanının üyeleridir. Bu, ad alanının bildirim alanında bildirilen adlara doğrudan karşılık gelir.
Ad alanlarının erişim kısıtlaması yoktur. Özel, korumalı veya iç ad alanları bildirmek mümkün değildir ve ad alanı adları her zaman genel olarak erişilebilir.
7.4.3 Yapı üyeleri
Bir yapının üyeleri, yapısında bildirilen üyeler ve yapının doğrudan temel sınıfından ve dolaylı temel sınıfından System.ValueType
devralınan üyelerdir object
.
Basit bir türün üyeleri, basit türün takma adı olan yapı türünün üyelerine doğrudan karşılık gelir (§8.3.5).
7.4.4 Numaralandırma üyeleri
Bir numaralandırma üyeleri, numaralandırmada bildirilen sabitler ve doğrudan temel sınıfı System.Enum
ile dolaylı temel sınıflar System.ValueType
ve object
'den devralınan üyelerden oluşur.
7.4.5 Sınıf üyeleri
Sınıfın üyeleri, sınıfında bildirilen üyeler ve temel sınıftan devralınan üyelerdir (temel sınıfı olmayan sınıf object
hariç). Temel sınıftan devralınan üyeler temel sınıfın sabitlerini, alanlarını, yöntemlerini, özelliklerini, olaylarını, dizin oluşturucularını, işleçlerini ve türlerini içerir, ancak temel sınıfın örnek oluşturucularını, sonlandırıcılarını ve statik oluşturucularını içermez. Temel sınıf üyeleri, erişilebilirliklerine bakılmaksızın devralınır.
Sınıf bildirimi sabitlerin, alanların, yöntemlerin, özelliklerin, olayların, dizin oluşturucuların, işleçlerin, örnek oluşturucularının, sonlandırıcıların, statik oluşturucuların ve türlerin bildirimlerini içerebilir.
object
(§8.2.3) ve string
(§8.2.5) üyeleri, diğer ad olarak kullandıkları sınıf türlerinin üyelerine doğrudan karşılık gelir.
7.4.6 Arabirim üyeleri
Bir arabirimin üyeleri, arabirimde ve arabirimin tüm temel arabirimlerinde bildirilen üyelerdir.
Not: Sınıftaki
object
üyeler hiçbir arabirimin (§18.4) üyesi değildir. Ancak, sınıftakiobject
üyeler herhangi bir arabirim türünde (§12.5) üye arama yoluyla kullanılabilir. dipnot
7.4.7 Dizi üyeleri
Bir dizinin üyeleri sınıfından System.Array
devralınan üyelerdir.
7.4.8 Temsil edilen üyeler
Temsilci, System.Delegate
sınıfından üyeleri devralır. Ayrıca, bildiriminde belirtilen aynı dönüş türüne ve parametre listesine sahip bir yöntem olan Invoke
, §20.2'yi içerir. Bu yöntemin çağrılması, aynı temsilci örneğindeki bir temsilci çağrısıyla (§20.6) aynı şekilde davranacaktır.
Bir uygulama, devralma yoluyla veya doğrudan temsilcinin kendisinde ek üyeler sağlayabilir.
7.5 Üye erişimi
7.5.1 Genel
Üyelerin bildirimleri, üye erişimi üzerinde denetime izin verir. Üyenin erişilebilirliği, üyenin bildirilen erişilebilirliği (§7.5.2) tarafından belirlenir ve varsayılan olarak, doğrudan içeren türün erişilebilirliği ile birleştirilir.
Belirli bir üyeye erişim izni verildiğinde, üyenin erişilebilir olduğu söylenir. Buna karşılık, belirli bir üyeye erişime izin verilmediğinde, üyenin erişilemez olduğu söylenir. Üyeye erişim, erişimin gerçekleştiği metinsel konum üyenin erişilebilirlik etki alanına (§7.5.3) dahil edildiğinde izin verilir.
7.5.2 Bildirilen erişilebilirlik
Bir üyenin bildirilen erişilebilirliği aşağıdakilerden biri olabilir:
- Üye bildirimine bir
public
değiştirici ekleyerek seçilen Genel. Sezgisel anlamıpublic
"erişim sınırlı değildir". - Korumalı, üye bildirimine bir
protected
değiştirici ekleyerek seçilir. sezgisel anlamıprotected
"erişim içindeki sınıf veya içindeki sınıftan türetilmiş türlerle sınırlıdır". - Üye bildirimine bir
internal
değiştirici eklenerek seçilen, "Internal"dir. Sezgisel anlamıinternal
"bu assembly'e kısıtlı erişim"dir. - Korumalı iç erişimi, üye bildirimine hem
protected
hem deinternal
değiştiricileri eklenerek seçilir.protected internal
ifadesinin sezgisel anlamı, "hem bu derlemede hem de içeren sınıftan türetilen türlerde erişilebilir" şeklindedir. - Üye bildirimine bir
private
veprotected
değiştiricisini ekleyerek seçilen özel korumalı. sezgisel anlamıprivate protected
"bu derleme içinde, içeren sınıf ve içeren sınıftan türetilen türler tarafından erişilebilir." - Üye bildirimine bir
private
değiştirici ekleyerek "Özel" olarak seçilen. Sezgisel anlamıprivate
"erişim, içeren türle sınırlıdır".
Üye bildiriminin gerçekleştiği bağlama bağlı olarak, yalnızca belirli türlerde bildirilen erişilebilirlik izin verilir. Ayrıca, bir üye bildirimi herhangi bir erişim değiştiricisi içermediğinde, bildirimin gerçekleştiği bağlam varsayılan bildirilen erişilebilirliği belirler.
- Ad alanları, doğası gereği
public
bildirilmiş erişilebilirliğe sahiptir. Ad alanı bildirimlerinde erişim değiştiricisine izin verilmez. - Doğrudan derleme birimleri veya ad alanlarında bildirilen türler (diğer türlerin aksine), bildirilen erişim düzeyi
public
veyainternal
olabilir ve varsayılan olarakinternal
bildirilen erişim düzeyine sahiptir. - Sınıf üyeleri izin verilen türlerden herhangi birine sahip olabilir ve varsayılan olarak
private
bildirilen erişilebilirlik seviyesine sahip olur.Not: Bir sınıfın üyesi olarak bildirilen bir tür izin verilen türlerden herhangi birine sahip olabilir, ancak bir ad alanının üyesi olarak bildirilen bir tür yalnızca
public
veyainternal
bildirilen erişilebilirlik içerebilir. dipnot - Yapı üyeleri,
public
,internal
veyaprivate
olarak bildirilen erişilebilirliğe sahip olabilir ve varsayılan olarakprivate
erişilebilirlikte bulunur, çünkü yapılar örtük olarak mühürlenmiştir. Birstruct
olarak tanıtılan yapı üyeleri (yani bu yapı tarafından devralınmamış olanlar)protected
,protected internal
veyaprivate protected
bildirilmiş erişilebilirliğe sahip olamaz.Not: Bir yapının üyesi olarak bildirilen bir tür,
public
,internal
veyaprivate
olarak bildirilen erişilebilirliğe sahip olabilirken, bir ad alanının üyesi olarak bildirilen bir tür yalnızcapublic
veyainternal
olarak bildirilen erişilebilirliğe sahip olabilir. dipnot - Arabirim üyeleri
public
bildirilen erişilebilirliğe sahiptir. Arabirim üyesi bildirimlerinde erişim değiştiricisine izin verilmez. - Numaralandırma üyeleri örtük olarak erişilebilirlik bildirmiş
public
. Numaralandırma üyesi bildirimlerinde erişim değiştiricisine izin verilmez.
7.5.3 Erişilebilirlik etki alanları
Üyenin erişilebilirlik etki alanı , üyeye erişime izin verilen program metninin (muhtemelen kopuk) bölümlerinden oluşur. Bir üyenin erişilebilirlik etki alanını tanımlama amacıyla, bir üyenin bir tür içinde bildirilmemesi durumunda en üst düzey olduğu ve başka bir tür içinde bildirilmesi durumunda üyenin iç içe yerleştirileceği söylenir. Ayrıca, bir programın program metni, programın tüm derleme birimlerinde bulunan tüm metinler olarak tanımlanır ve bir türün program metni, bu türün type_declarationsn içinde yer alan tüm metinler (büyük olasılıkla, türün içinde iç içe yerleştirilmiş türler dahil) olarak tanımlanır.
Önceden tanımlanmış bir türün (örn. object
, int
veya double
) erişilebilirlik etki alanı sınırsızdır.
Bir programda bildirilen bir üst düzey serbest tür T
(§8.4.4) erişilebilirlik etki alanı aşağıdaki gibi tanımlanır:
- Eğer
T
'nin bildirilen erişilebilirliği kamusal ise,T
etki alanının erişilebilirliği,P
'nin program metni veP
'e başvuran herhangi bir programdır. - Bildirilen erişilebilirliği
T
içeriyorsa,T
'in erişilebilirlik etki alanıP
'nin program metnidir.
Not: Bu tanımlardan, bir üst düzey ilişkisiz türün erişilebilirlik etki alanının her zaman en azından o türün bildirildiği programın program metni olduğunu izler. dipnot
Bir yapı türü T<A₁, ..., Aₑ>
için erişilebilirlik etki alanı, ilişkisiz genel türün erişilebilirlik etki alanının ve tür T
bağımsız değişkenlerinin erişilebilirlik etki alanlarının kesişimidir A₁, ..., Aₑ
.
bir program M
içindeki bir tür T
içinde bildirilen iç içe üyenin P
erişilebilirlik alanı aşağıdaki gibi tanımlanır (kendisinin bir tür olabileceğine dikkat edin M
):
- Eğer
M
'nin bildirilen erişilebilirliğipublic
ise,M
'nin erişilebilirlik etki alanıT
'ün erişilebilirlik etki alanıdır. -
M
bildirilen erişilebilirlikprotected internal
ise,D
P
program metni ileT
dışında bildirilenP
türünden türetilen herhangi bir program metninin birleşimi olsun.M
erişilebilirlik etki alanı,T
erişilebilirlik etki alanı ileD
'nin kesişimidir. - **
Verilen
M
erişilebilirliğiprivate protected
ise,D
;P
veT
program metinlerinin veT
türünden türetilmiş herhangi bir türün kesişimi olsun.M
erişilebilirlik etki alanı,T
erişilebilirlik etki alanı ileD
'nin kesişimidir. M
öğesinin bildirilen erişilebilirliğiprotected
ise,D
öğesininT
veT
'dan türetilen herhangi bir türün program metninin birleşimi olması sağlansın.M
erişilebilirlik etki alanı,T
erişilebilirlik etki alanı ileD
'nin kesişimidir.- Eğer
M
'ın bildirilen erişilebilirliğiinternal
ise,M
'ın erişilebilirlik etki alanı,T
'ın erişilebilirlik etki alanı ileP
'ün program metninin kesişimidir. - Bir
M
'nin bildirilen erişilebilirliğiprivate
ise,M
'nin erişilebilirlik etki alanı,T
'ün program metnidir.
Not: Bu tanımlardan çıkar ki, iç içe bir üyenin erişim alanı her zaman en azından üyenin bildirildiği türdeki program metnidir. Ayrıca, bir üyenin erişilebilirlik etki alanı, üyenin bildirildiği türün erişilebilirlik etki alanından hiçbir zaman daha kapsayıcı değildir. dipnot
Not: Sezgisel olarak, bir türe veya üyeye
M
erişildiğinde, erişime izin verildiğinden emin olmak için aşağıdaki adımlar değerlendirilir:
- İlk olarak,
M
bir tür içinde bildirildiğinde (bir derleme birimi veya ad alanına kıyasla), o tür erişilebilir değilse bir derleme zamanı hatası oluşur.- Ardından, eğer
M
public
ise, erişime izin verilir.- Aksi takdirde,
M
protected internal
ise, erişim bildirildiğiM
program içinde gerçekleşirse veya bildirildiği sınıftan türetilmiş bir sınıf içinde, türetilmiş sınıf türü aracılığıyla (M
) gerçekleşirse izin verilir.- Aksi takdirde,
M
protected
ise, erişime,M
sınıfı içinde gerçekleşiyorsa veyaM
sınıfından türetilmiş bir sınıfta türetilmiş sınıf türü üzerinden gerçekleşiyorsa (§7.5.4) izin verilir.- Aksi takdirde,
M
internal
ise,M
bildirildiği program içinde gerçekleşirse erişime izin verilir.- Aksi takdirde,
M
private
ise,M
bildirilmiş olduğu tür içinde gerçekleşirse erişime izin verilir.- Aksi takdirde, tür veya üye erişilemez ve derleme zamanı hatası oluşur. dipnot
Örnek: Aşağıdaki kodda
public class A { public static int X; internal static int Y; private static int Z; } internal class B { public static int X; internal static int Y; private static int Z; public class C { public static int X; internal static int Y; private static int Z; } private class D { public static int X; internal static int Y; private static int Z; } }
sınıflar ve üyeler aşağıdaki erişilebilirlik etki alanlarına sahiptir:
A
veA.X
erişilebilirlik etki alanı sınırsızdır.A.Y
,B
,B.X
,B.Y
,B.C
,B.C.X
veB.C.Y
erişilebilirlik etki alanı, içeren programın program metnidir.- erişilebilirlik etki alanı
A.Z
, program metnidirA
.B.Z
veB.D
öğelerinin erişilebilirlik etki alanı,B
program metni olup, bu metinB.C
veB.D
program metinlerini de içerir.- erişilebilirlik etki alanı
B.C.Z
, program metnidirB.C
.B.D.X
veB.D.Y
öğelerinin erişilebilirlik etki alanı,B
program metni olup, bu metinB.C
veB.D
program metinlerini de içerir.- erişilebilirlik etki alanı
B.D.Z
, program metnidirB.D
. Örnekte gösterildiği gibi, bir üyenin erişilebilirlik etki alanı hiçbir zaman içeren türden büyük değildir. Örneğin, tümX
üyeleri genel olarak bildirilen erişilebilirliğe sahip olsa da,A.X
dışında kalanların erişilebilirlik etki alanları bunları içeren bir tür tarafından kısıtlanmıştır.son örnek
§7.4'te açıklandığı gibi, örnek oluşturucuları, sonlandırıcılar ve statik oluşturucular dışında bir temel sınıfın tüm üyeleri türetilmiş türler tarafından devralınır. Bu, bir temel sınıfın özel üyelerini bile içerir. Ancak, özel üyenin erişilebilirlik etki alanı yalnızca üyenin bildirildiği türdeki program metnini içerir.
Örnek: Aşağıdaki kodda
class A { int x; static void F(B b) { b.x = 1; // Ok } } class B : A { static void F(B b) { b.x = 1; // Error, x not accessible } }
B
sınıfı,x
sınıfından özel üyeA
'yi devralır. Üye özel olduğundan, yalnızca class_body içindeA
erişilebilir. Bu nedenle, erişimib.x
yöntemindeA.F
başarılı olur, ancak yöntemindeB.F
başarısız olur.son örnek
7.5.4 Korumalı erişim
Bir protected
veya private protected
örnek üyesine bildirildiği sınıfın program metni dışında erişildiğinde ve bir protected internal
örnek üyesine bildirildiği programın program metni dışında erişildiğinde, erişim, bildirildiği sınıftan türetilen bir sınıf bildirimi içinde gerçekleşir. Ayrıca, erişimin, türetilmiş sınıf türünün bir örneği veya ondan oluşturulmuş bir sınıf türü aracılığıyla yapılması gereklidir. Bu kısıtlama, üyeler aynı temel sınıftan devralınsa bile türetilmiş bir sınıfın diğer türetilmiş sınıfların korumalı üyelerine erişmesini engeller.
B
, korumalı bir örnek üye olan M
'i bildiren bir temel sınıf olsun ve D
, B
'ten türetilen bir sınıf olsun.
class_body içinde, D
öğesine erişim, aşağıdaki formlardan birine sahip olabilir:
- Nitelenmemiş bir type_name veya primary_expression formu
M
. -
biçiminde bir
E.M
; buradaE
türüT
ya daT
'den türetilmiş bir sınıf olduğunda,T
iseD
sınıfı veyaD
'den oluşturulmuş bir sınıf türüdür. - Bir primary_expression biçiminde
base.M
. - Bir primary_expression
base[
argument_list]
biçimindedir.
Türetilmiş bir sınıf, bu erişim biçimlerine ek olarak bir constructor_initializer (§15.11.2) içindeki bir temel sınıfın korumalı örnek oluşturucusüne erişebilir.
Örnek: Aşağıdaki kodda
public class A { protected int x; static void F(A a, B b) { a.x = 1; // Ok b.x = 1; // Ok } } public class B : A { static void F(A a, B b) { a.x = 1; // Error, must access through instance of B b.x = 1; // Ok } }
içinde
A
, her iki durumda dax
veA
örnekleri aracılığıylaB
'e erişim mümkündür, çünkü erişim,A
veyaA
'dan türetilmiş bir sınıfın örneği üzerinden gerçekleşir. Ancak,B
içinde birx
örneği üzerindenA
'e erişmek mümkün değildir, çünküA
B
'den türetilmez.son örnek
Örnek:
class C<T> { protected T x; } class D<T> : C<T> { static void F() { D<T> dt = new D<T>(); D<int> di = new D<int>(); D<string> ds = new D<string>(); dt.x = default(T); di.x = 123; ds.x = "test"; } }
Burada, üç atama
x
'e izinlidir çünkü hepsi, genel tipten türetilmiş sınıf türü örnekleri yoluyla gerçekleştirilir.son örnek
Not: Genel sınıfta bildirilen korumalı bir üyenin erişilebilirlik etki alanı (§7.5.3), bu genel sınıftan oluşturulan herhangi bir türden türetilen tüm sınıf bildirimlerinin program metnini içerir. Örnekte:
class C<T> { protected static T x; } class D : C<string> { static void Main() { C<int>.x = 5; } }
protected
öğesineC<int>.x
üyesine yapılan başvuru,D
sınıfıD
'den türetilmiş olsa bile geçerlidir. dipnot
7.5.5 Erişilebilirlik kısıtlamaları
C# dilindeki çeşitli yapılar, bir türün en az üye veya başka bir tür kadar erişilebilir olmasını gerektirir.
T
türünün erişilebilirlik etki alanı, M
türü veya üyesinin T
erişilebilirlik etki alanının bir üst kümesiyse, M
türünün veya üyesinin en azından bu tür kadar erişilebilir olduğu söylenir. Başka bir deyişle, `T
`, `M
` erişilebilir olduğu tüm bağlamlarda `T
` erişilebilir olduğunda, en az `M
` kadar erişilebilirdir.
Aşağıdaki erişilebilirlik kısıtlamaları vardır:
- Bir sınıf türünün doğrudan temel sınıfı en az sınıf türünün kendisi kadar erişilebilir olmalıdır.
- Bir arabirim türünün açık taban arabirimleri en az arabirim türünün kendisi kadar erişilebilir olmalıdır.
- Temsilci türünün dönüş türü ve parametre türleri en az temsilci türünün kendisi kadar erişilebilir olmalıdır.
- Sabitin türü en az sabitin kendisi kadar erişilebilir olmalıdır.
- Bir alanın türü en az alanın kendisi kadar erişilebilir olmalıdır.
- Bir yöntemin dönüş türü ve parametre türleri en az yöntemin kendisi kadar erişilebilir olmalıdır.
- Bir özelliğin türü, en az mülkiyetin kendisi kadar erişilebilir olmalıdır.
- Bir olayın türü en az olayın kendisi kadar erişilebilir olmalıdır.
- Dizin oluşturucunun türü ve parametre türleri en az dizin oluşturucunun kendisi kadar erişilebilir olmalıdır.
- Bir işlecin dönüş türü ve parametre türleri en az operatörün kendisi kadar erişilebilir olmalıdır.
- Örnek oluşturucusunun parametre türleri en az örnek oluşturucusunun kendisi kadar erişilebilir olmalıdır.
- Tür parametresindeki bir arabirim veya sınıf türü kısıtlaması, kısıtlamayı bildiren üye kadar erişilebilir olmalıdır.
Örnek: Aşağıdaki kodda
class A {...} public class B: A {...}
B
sınıfı,A
en azB
kadar erişilebilir olmadığından derleme zamanı hatası verir.son örnek
Örnek: Benzer şekilde, aşağıdaki kodda
class A {...} public class B { A F() {...} internal A G() {...} public A H() {...} }
içindeki
H
yöntemiB
, dönüş türüA
en az yöntem kadar erişilebilir olmadığından derleme zamanı hatasıyla sonuçlanır.son örnek
7.6 İmzalar ve aşırı yükleme
Yöntemler, örnek oluşturucuları, dizin oluşturucular ve işleçler imzalarıyla karakterize edilir:
- Bir yöntemin imzası yöntemin adından, tür parametrelerinin sayısından ve parametrelerinin her birinin türünden ve parametre geçirme modundan oluşur ve soldan sağa doğru sırayla kabul edilir. Bu amaçlarla, bir parametre türünde oluşan yöntemin herhangi bir tür parametresi, adıyla değil, yöntemin tür parametre listesindeki sıralı konumuyla tanımlanır. Bir yöntemin imzası özellikle dönüş türünü, parametre adlarını, tür parametre adlarını, tür parametre kısıtlamalarını, veya
params
parametre değiştiricilerini ya da parametrelerinthis
gerekli veya isteğe bağlı olup olmadığını içermez. - Bir örnek oluşturucusunun imzası, parametrelerinin her birinin türünden ve parametre geçirme modundan oluşur ve soldan sağa sırayla kabul edilir. Örnek oluşturucusunun imzası özellikle en doğru parametre için belirtilebilen değiştiriciyi veya parametrelerin gerekli mi yoksa isteğe bağlı mı olduğunu içermez
params
. - Dizin oluşturucunun imzası, parametrelerinin her birinin türünden oluşur ve soldan sağa doğru sırasıyla kabul edilir. Bir dizin oluşturucunun imzası özel olarak öğe türünü içermez veya en doğru parametre için belirtilebilen değiştiriciyi veya parametrelerin gerekli veya isteğe bağlı olup olmadığını içermez
params
. - bir işlecin imzası, işlecin adından ve parametrelerinin her birinin türünden oluşur ve soldan sağa doğru sırasıyla kabul edilir. Bir işlecin imzası özellikle sonuç türünü içermez.
- Dönüştürme işlecinin imzası kaynak türünden ve hedef türünden oluşur. Dönüştürme işlecinin örtük veya açık sınıflandırması imzanın bir parçası değildir.
- Aynı üye türündeki iki imza (yöntem, örnek oluşturucu, dizin oluşturucu veya işleç) aynı ada, tür parametresi sayısına, parametre sayısına ve parametre geçirme modlarına sahipse aynı imza olarak kabul edilir ve karşılık gelen parametrelerin türleri (§10.2.2) arasında bir kimlik dönüştürmesi vardır.
İmzalar sınıflarda, yapılarda ve arabirimlerde üyelerin aşırı yüklenmesini sağlayan mekanizmadır:
- Yöntemlerin aşırı yüklenmesi, bir sınıfın, yapının veya arabirimin, imzalarının bu sınıf, yapı veya arabirim içinde benzersiz olması koşuluyla aynı ada sahip birden çok yöntemi bildirmesine izin verir.
- Örnek oluşturucularının aşırı yüklenmesi, bir sınıfın veya yapının, imzalarının bu sınıf veya yapı içinde benzersiz olması koşuluyla birden çok örnek oluşturucuyu bildirmesine izin verir.
- Dizin oluşturucuların aşırı yüklenmesi, bir sınıf, yapı veya arabirimin, imzalarının bu sınıf, yapı veya arabirim içinde benzersiz olması koşuluyla birden çok dizin oluşturucu bildirmesine izin verir.
- İşleçlerin aşırı yüklenmesi, bir sınıfın veya yapının, imzaları bu sınıf veya yapı içinde benzersiz olması koşuluyla aynı ada sahip birden çok işleç bildirmesine izin verir.
Parametre değiştiricileri, in
, out
ve ref
imzanın bir parçası olarak kabul edilse de, tek bir türde bildirilen üyeler, imzada yalnızca in
, out
ve ref
ile farklı olamaz. Aynı türdeki iki üye, her iki yöntem için out
veya in
değiştiricilerine sahip tüm parametreler ref
değiştiricilere dönüştürüldüğünde imzaları aynı olacak şekilde bildirilirse, derleme zamanı hatası oluşur. İmza eşleştirmenin diğer amaçları (ör. gizleme veya geçersiz kılma), in
, out
ve ref
imzanın bir parçası olarak kabul edilir ve birbiriyle eşleşmez.
Not: Bu kısıtlama, C# programlarının ortak dil altyapısında (CLI) çalıştırılacak şekilde kolayca çevrilebilmesini sağlamaktır. Bu, yalnızca ,
in
veout
içinderef
farklı yöntemleri tanımlamanın bir yolunu sağlamaz. dipnot
object
ve dynamic
türleri, imzalar karşılaştırılırken ayırt edilmemektedir. Bu nedenle, imzaları yalnızca object
ile dynamic
değiştirilerek farklı olan üyelerin tek bir türde bildirilmesine izin verilmez.
Örnek: Aşağıdaki örnekte, imzalarıyla birlikte bir dizi aşırı yüklenmiş yöntem bildirimi gösterilmektedir.
interface ITest { void F(); // F() void F(int x); // F(int) void F(ref int x); // F(ref int) void F(out int x); // F(out int) error void F(object o); // F(object) void F(dynamic d); // error. void F(int x, int y); // F(int, int) int F(string s); // F(string) int F(int x); // F(int) error void F(string[] a); // F(string[]) void F(params string[] a); // F(string[]) error void F<S>(S s); // F<0>(0) void F<T>(T t); // F<0>(0) error void F<S,T>(S s); // F<0,1>(0) void F<T,S>(S s); // F<0,1>(1) ok }
Tüm
in
,out
veref
parametre değiştiricilerinin (§15.6.2) imzanın parçası olduğunu unutmayın. Bu nedenle,F(int)
,F(in int)
,F(out int)
veF(ref int)
tüm benzersiz imzalardır. Ancak,F(in int)
,F(out int)
veF(ref int)
yalnızcain
,out
veref
ile farklılık gösterdiği için aynı arabirim içinde bildirilemez. Ayrıca, dönüş türünün ve değiştiricininparams
imzanın parçası olmadığını unutmayın, bu nedenle yalnızca dönüş türüne veya değiştiricinin eklenmesine veya dışlanmasınaparams
bağlı olarak aşırı yükleme yapılamaz. Bu nedenle, yukarıda tanımlananF(int)
veF(params string[])
yöntemlerinin bildirimleri bir derleme zamanı hatasına neden olur. son örnek
7.7 Kapsamlar
7.7.1 Genel
Bir adın kapsamı , adın niteliği olmadan adla bildirilen varlığa başvurmanın mümkün olduğu program metninin bölgesidir. Kapsamlar iç içe geçmiş olabilir ve iç kapsam, dış kapsamdaki bir ismin anlamını yeniden tanımlayabilir. (Ancak bu, §7.3 tarafından uygulanan, iç içe bir blokta, kapsayan bir bloktaki yerel değişken veya yerel sabit ile aynı ada sahip bir yerel değişken veya yerel sabit bildirmenin mümkün olmadığı kısıtlamayı kaldırmaz.) Daha sonra dış kapsamdaki adın, iç kapsamın kapsadığı program metni bölgesinde "gizli" olduğu söylenir ve dış adı erişmek yalnızca adın nitelenmesiyle mümkündür.
namespace_declaration ile kapsamayan bir namespace_member_declaration (§14.6) tarafından bildirilen bir ad alanı üyesinin kapsamı, program metninin tamamıdır.
namespace_declaration adı tamamen belirtilmiş bir namespace_member_declaration tarafından bildirilen bir ad alanı üyesinin kapsamı, tam adı
N
olan veya ile başlayan her namespace_declaration'ınN
'sini kapsar ve ardından bir nokta gelir.extern_alias_directive (§14.4) tarafından tanımlanan bir adın kapsamı, doğrudan içeren compilation_unit veya namespace_body içinde, using_directive’ler, global_attributes ve namespace_member_declaration’lar üzerinde genişler. Bir extern_alias_directive, temel alınan bildirim alanına yeni üye eklemez. Başka bir deyişle, bir extern_alias_directive geçişli değildir; bunun yerine, yalnızca yer aldığı derleme_birimi veya ad_alanı_gövdesini etkiler.
Using_directive (§14.5) tarafından tanımlanan veya içe aktarılan bir adın kapsamı, using_directive'in oluştuğu compilation_unit veya namespace_body içindeki global_attributes ve namespace_member_declaration'ları üzerinde genişletilir. Bir using_directive, belirli bir compilation_unit veya namespace_body içerisinde sıfır veya daha fazla ad alanı veya tür adını kullanılabilir hale getirebilir, ancak temel bildirim alanına yeni üyeler eklemez. Başka bir deyişle, bir using_directive geçişli değildir; yalnızca ortaya çıktığı derleme_birimi (compilation_unit) veya ad_alanı_gövdesi (namespace_body) etkiler.
sınıf bildirimi (§15.2) üzerindeki tür parametresi listesi tarafından bildirilen bir tür parametresinin kapsamı, bu sınıf bildirimi'nin sınıf temeli, tür parametresi kısıtlama maddelerive sınıf gövdesi'dir.
Not: Sınıfın üyelerinden farklı olarak, bu kapsam türetilmiş sınıflara genişletilmez. dipnot
Struct_declaration üzerindeki bir type_parameter_list tarafından bildirilen bir tür parametresinin kapsamı, struct_interfaces, type_parameter_constraints_clause'ler ve o struct_declaration’ın struct_body’sidir.
Bir interface_declaration (§18.2) üzerindeki type_parameter_list tarafından bildirilen bir tür parametresinin kapsamı, o interface_declaration'ın interface_base'ı, type_parameter_constraints_clause'ları ve interface_body'sidir.
tr-TR: Bir delegate_bildirimi üzerindeki bir tür_parametresi_listesi tarafından bildirilen bir tür parametresinin kapsamı, o delegate_bildirimi'nin dönüş_türü, parametre_listesi ve tür_parametresi_kısıtlamaları_cümlesidir.
type_parameter_list ile bir method_declaration (§15.6.1) üzerinde bildirilen bir tür parametresinin kapsamı method_declaration'dur.
class_member_declaration (§15.3.1) tarafından bildirilen bir üyenin kapsamı, bildirimin gerçekleştiği class_body'dir. Ayrıca, bir sınıf üyesinin kapsamı, üyenin erişilebilirlik etki alanına (§7.5.3) dahil edilen türetilmiş sınıfların sınıf_gövdesine uzanır.
struct_member_declaration (§16.3) tarafından bildirilen bir üyenin kapsamı, bildirimin gerçekleştiği struct_body'dir.
enum_member_declaration (§19.4) tarafından bildirilen bir üyenin kapsamı, bildirimin meydana geldiği enum_body'dir.
method_declaration (§15.6) içinde bildirilen bir parametrenin kapsamı, o method_body veya ref_method_body içindir.
Bir indexer_declaration (§15.9) içinde bildirilen bir parametrenin kapsamı, o indexer_declaration'ın indexer_body'sidir.
operator_declaration (§15.10) olarak bildirilen bir parametrenin kapsamı, o operator_declaration içindeki operator_body'dir.
Bir parametrenin `constructor_declaration` (§15.11) içindeki kapsamı, o `constructor_declaration`'un `constructor_initializer` ve `bloğu`dur.
lambda_expression (§12.19) ile bildirilen bir parametrenin kapsamı, o lambda_expression içindeki lambda_expression_body'dir.
anonymous_method_expression (§12.19) içinde bildirilen bir parametrenin kapsamı, o anonymous_method_expression bloğudur.
labeled_statement (§13.5) olarak bildirilen bir etiketin kapsamı, bildirimin gerçekleştiği blok olur.
local_variable_declaration (§13.6.2) içinde bildirilen bir yerel değişkenin kapsamı, bildirimin gerçekleştiği blok olur.
Bir switch_block içinde bildirilen yerel değişkenin kapsamı
switch
switch_block'tır (§13.8.3).Bir for_initializer bildiriminde (§13.9.4) tanımlanan yerel değişkenin kapsamı,
for
deyiminin for_initializer, for_condition, for_iterator ve embedded_statement bölümlerini içerir.bir local_constant_declaration (§13.6.3) içinde bildirilen yerel sabitin kapsamı, bildirimin gerçekleştiği blok olur. Derleme zamanı hatası, constant_declarator'dan önce gelen bir metin konumunda yerel sabite başvurmaktır.
bir foreach_statement, using_statement, lock_statement veya query_expression parçası olarak bildirilen bir değişkenin kapsamı, verilen yapısının genişletilmesiyle belirlenir.
Ad alanı, sınıf, yapı veya numaralandırma üyesi kapsamında, üyenin bildiriminden önceki metinsel bir konumda üyeye başvurmak mümkündür.
Örnek:
class A { void F() { i = 1; } int i = 0; }
Burada,
F
'nin bildirilmeden öncei
'e başvurması geçerlidir.son örnek
Yerel değişken kapsamında, yerel değişkene deyimcisinden önce gelen metinsel bir konumda atıfta bulunmak bir derleme zamanı hatasıdır.
Örnek:
class A { int i = 0; void F() { i = 1; // Error, use precedes declaration int i; i = 2; } void G() { int j = (j = 1); // Valid } void H() { int a = 1, b = ++a; // Valid } }
Özellikle yukarıdaki yöntemde,
F
'ya yapılan ilk atama, dış kapsamda bildirilen alana başvurmaz. Aslında, yerel değişkene başvurur ve değişken bildiriminin öncesinde yer aldığı için derleme sırasında bir hataya yol açar.G
yönteminde,j
bildirimi içinj
başlatıcıda kullanılması geçerlidir çünkü kullanım bildirimciden önce gelmez.H
yönteminde, daha sonra gelen bildirimci, aynı local_variable_declaration içindeki önceki bir bildirimciyle bildirilen yerel değişkene doğru şekilde başvurur.son örnek
Not: Yerel değişkenler ve yerel sabitler için kapsam kuralları, ifade bağlamında kullanılan bir adın anlamının bir blok içinde her zaman aynı olmasını garanti etmek için tasarlanmıştır. Yerel değişkenin kapsamı yalnızca bildiriminden bloğun sonuna kadar genişletilecekse, yukarıdaki örnekte ilk atama örnek değişkenine, ikinci atama ise yerel değişkene atanır ve bloğun deyimleri daha sonra yeniden düzenlenirse derleme zamanı hatalarına yol açabilir.)
Bir blok içindeki bir adın anlamı, adın kullanıldığı bağlama göre farklılık gösterebilir. Örnekte
class A {} class Test { static void Main() { string A = "hello, world"; string s = A; // expression context Type t = typeof(A); // type context Console.WriteLine(s); // writes "hello, world" Console.WriteLine(t); // writes "A" } }
adı
A
ifade bağlamında yerel değişkenA
'e, tür bağlamında ise sınıfaA
başvurmak için kullanılır.dipnot
7.7.2 Adı gizleme
7.7.2.1 Genel
Bir varlığın kapsamı genellikle varlığın bildirim alanından daha fazla program metnini kapsar. Özellikle, bir varlığın kapsamı, aynı ada sahip varlıkları içeren yeni bildirim alanlarını tanıtan bildirimleri içerebilir. Bu tür bildirimler özgün varlığın gizlenmesini sağlar. Buna karşılık, bir varlığın gizlenmediğinde görünür olduğu söylenir.
Kapsamlar iç içe yerleştirme veya devralma yoluyla çakıştığında ad gizleme gerçekleşir. İki gizleme türünün özellikleri aşağıdaki alt dallarda açıklanmıştır.
7.7.2.2 İç içe yerleştirme aracılığıyla gizleme
İç içe yerleştirme aracılığıyla gizlenen ad, ad alanlarının veya türlerin ad alanlarının içinde iç içe geçmenin bir sonucu olarak, sınıfların veya yapıların içindeki türlerin iç içe geçmelerinin bir sonucu olarak, yerel bir işlevin veya lambdanın sonucu olarak ve parametre, yerel değişken ve yerel sabit bildirimlerinin bir sonucu olarak ortaya çıkabilir.
Örnek: Aşağıdaki kodda
class A { int i = 0; void F() { int i = 1; void M1() { float i = 1.0f; Func<double, double> doubler = (double i) => i * 2.0; } } void G() { i = 1; } }
F
yönteminde, örnek değişkeni
, yerel değişkeni
tarafından gizlenir, ancakG
yönteminin içinde,i
yine de örnek değişkene başvurur. yerel işlevM1
içinde,float i
hemen dışındakii
gizler. lambda parametresii
, lambda gövdesininfloat i
içini gizler.son örnek
İç kapsamdaki bir ad, dış kapsamdaki bir adı gizlediğinde, bu adın tüm aşırı yüklenmiş hâllerini gizler.
Örnek: Aşağıdaki kodda
class Outer { static void F(int i) {} static void F(string s) {} class Inner { static void F(long l) {} void G() { F(1); // Invokes Outer.Inner.F F("Hello"); // Error } } }
Çağrı
F(1)
,F
içinde ilan edilenInner
'i çağırır çünküF
'ün tüm dış oluşumları iç bildirim tarafından gizlenir. Aynı nedenle, çağrıF("Hello")
bir derleme zamanı hatasıyla sonuçlanır.son örnek
7.7.2.3 Devralma yoluyla gizleniyor
Devralma yoluyla ad gizleme, sınıflar veya yapılar, temel sınıflardan devralınan adları yeniden tanımladığında meydana gelir. Bu tür bir adı gizlemek aşağıdaki formlardan birini alır:
- Bir sınıf veya yapıda tanıtılan sabit, alan, özellik, olay veya tür, aynı ada sahip tüm temel sınıf üyelerini gizler.
- Bir sınıf veya yapıda tanıtılan bir yöntem, aynı ada sahip tüm yöntem dışı temel sınıf üyelerini ve aynı imzaya sahip tüm temel sınıf yöntemlerini gizler (§7.6).
- Bir sınıf veya yapıda tanıtılan bir dizin oluşturucu, aynı imzaya (§7.6) sahip tüm temel sınıf dizin oluşturucularını gizler.
İşleç bildirimlerini (§15.10) yöneten kurallar, türetilmiş bir sınıfın bir temel sınıftaki işleçle aynı imzaya sahip bir işleci bildirmesini imkansız hale getirir. Bu nedenle, işleçler birbirlerini asla saklamaz.
Bir adı dış kapsamdan gizlemenin aksine, devralınan bir kapsamdan görünen bir adı gizlemek bir uyarının bildirilmesine neden olur.
Örnek: Aşağıdaki kodda
class Base { public void F() {} } class Derived : Base { public void F() {} // Warning, hiding an inherited name }
F
bildirimiDerived
içinde bir uyarının oluşmasına neden olur. Devralınan bir adı gizlemek özellikle bir hata değildir, çünkü bu temel sınıfların ayrı evrimini önleyebileceğinden. Örneğin, yukarıdaki durum,Base
'nin daha sonraki bir sürümünün, sınıfın önceki bir sürümünde bulunmayan birF
yöntemini tanıtması nedeniyle ortaya çıkmış olabilir.son örnek
Devralınan bir adı gizlemenin neden olduğu uyarı, değiştiricinin new
kullanımıyla ortadan kaldırılabilir:
Örnek:
class Base { public void F() {} } class Derived : Base { public new void F() {} }
new
modifikatörü,F
içindekiDerived
'nin "yeni" olduğunu ve gerçekten devralınan üyeyi gizlemeyi amaçladığını belirtir.son örnek
Yeni üye bildirimi, devralınan üyeyi yalnızca yeni üye kapsamında gizler.
Örnek:
class Base { public static void F() {} } class Derived : Base { private new static void F() {} // Hides Base.F in Derived only } class MoreDerived : Derived { static void G() { F(); // Invokes Base.F } }
Yukarıdaki örnekte,
F
'dekiDerived
tanımı,F
'ten devralınanBase
'yi gizler, ancakF
'deki yeniDerived
özel erişime sahip olduğundan, kapsamıMoreDerived
'ya kadar genişletilmez. Bu nedenle,F()
içindeMoreDerived.G
çağrısı geçerlidir veBase.F
'yi çağırır.son örnek
7.8 Ad alanı ve tür adları
7.8.1 Genel
C# programındaki çeşitli bağlamlar için bir namespace_name veya type_name belirtilmesi gerekir.
namespace_name
: namespace_or_type_name
;
type_name
: namespace_or_type_name
;
namespace_or_type_name
: identifier type_argument_list? ('.' identifier type_argument_list?)*
| qualified_alias_member ('.' identifier type_argument_list?)*
;
namespace_name, bir ad alanına başvuran bir ad_alanı_veya_tür_adıdir.
Çözüm, aşağıda açıklandığı gibi, bir namespace_or_type_name içindeki namespace_name bir ad alanına başvurmalıdır; aksi takdirde derleme zamanı hatası oluşur. Bir namespace_name içinde tür bağımsız değişkeni (§8.4.2) bulunamaz (yalnızca türlerde tür bağımsız değişkenleri olabilir).
type_name, bir türü ifade eden bir namespace_or_type_name'dir.
Çözüm aşağıda açıklandığı gibi gerçekleştikten sonra, bir type_name 'in namespace_or_type_name'i bir türe atıfta bulunmalıdır; aksi takdirde derleme zamanı hatası meydana gelir.
namespace_or_type_name bir türe veya ad alanına başvurur. Belirli bir ad alanının veya türün çözümü, dil bilgisi parçalarından biri olmak üzere dil bilgisini öndeki bir bölüme bölmeye dayalı iki adımı içerir:
identifier type_argument_list?
qualified_alias_member
ve dil bilgisi parçası olan sondaki bölüm:
('.' identifier type_argument_list?)*
İlk olarak, başlangıç ad alanını veya türünü belirlemek için R₀
baştaki bölüm çözümlenir.
namespace_or_type_name öncü kısmı bir qualified_alias_member ise, R₀
ad alanı veya türdür, bunu çözerek §14.8.1'de açıklandığı gibi.
Aksi takdirde, dil bilgisi parçası tanımlayıcı type_argument_list? olan baştaki bölüm şu biçimlerden birine sahip olur:
I
I<A₁, ..., Aₓ>
nerede:
-
I
tek bir tanımlayıcıdır; ve -
<A₁, ..., Aₓ>
bir type_argument_list olduğunda, hiçbir type_argument_list belirtilmezse,x
sıfır olarak kabul edilir.
R₀
aşağıdaki gibi belirlenir:
-
x
sıfırsa ve namespace_or_type_name, genel metod bildirimi (§15.6) içerisinde ancak yöntem üst bilgisininözniteliklerinin dışında görünüyorsa ve bu bildirim adında olan bir tür parametresi (I
) içeriyorsa, o tür parametresine işaret eder. - Aksi takdirde, eğer namespace_or_type_name bir tür bildirimi içinde görünüyorsa, her örnek türü
T
için (§15.3.2), bu tür bildiriminin örnek türüyle başlayıp her bir kapsayan sınıf veya yapı bildiriminin örnek türüyle devam eder (varsa):- Eğer
x
sıfırsa veT
bildirimiI
adında bir tür parametresi içeriyorsa, o zamanR₀
bu tür parametresine başvurur. - Aksi takdirde , namespace_or_type_name tür bildiriminin gövdesinde görünüyorsa ve
T
veya temel türlerinden herhangi biri adI
vex
tür parametrelerine sahip iç içe erişilebilir bir tür içeriyorsa,R₀
verilen tür bağımsız değişkenleriyle oluşturulmuş bu türe başvurur. Birden fazla tür varsa, daha fazla türetilmiş tür içinde bildirilen tür seçilir.Not: Tür olmayan üyeler (sabitler, alanlar, yöntemler, özellikler, dizin oluşturucular, işleçler, örnek oluşturucuları, sonlandırıcılar ve statik oluşturucular) ve farklı tür parametrelerine sahip tür üyeleri, namespace_or_type_name anlamını belirlerken yoksayılır. dipnot
- Aksi takdirde, her ad alanı
N
için, namespace_or_type_name oluştuğu ad alanıyla başlayarak, herhangi bir kapsayan ad alanıyla (varsa) devam ederek ve genel ad alanında sonlanarak, bir varlık bulunana kadar aşağıdaki adımlar değerlendirilir:- Eğer
x
sıfırsa veI
,N
içindeki bir ad alanının adıysa:- "Eğer namespace_or_type_name oluştuğu yer,
N
için bir ad alanı bildirimi tarafından çevrelenmişse ve bu ad alanı bildirimi, adı bir ad alanı veya türle ilişkilendiren bir extern_alias_directive veya using_alias_directive içeriyorsa,I
'ün adı belirsizleşir ve bir derleme zamanı hatası oluşur." - Aksi takdirde,
R₀
içindeI
adlıN
ad alanına başvurur.
- "Eğer namespace_or_type_name oluştuğu yer,
- Aksi takdirde,
N
isimI
vex
tür parametrelerine sahip erişilebilir bir tür içeriyorsa:-
x
sıfır ise ve namespace_or_type_name oluştuğu konumN
için bir ad alanı bildirimi ile çevrelenmişse ve ad alanı bildirimi, adı bir ad alanı veya türle ilişkilendiren bir extern_alias_directive veya using_alias_directive içeriyorsa,I
belirsizdir ve derleme zamanı hatası oluşur. - Aksi takdirde,
R₀
verilen tür bağımsız değişkenleriyle oluşturulan türe başvurur.
-
- Aksi halde, namespace_or_type_name'in oluştuğu konum
N
bir ad alanı bildirimiyle çevreleniyorsa:- Eğer
x
sıfır ise ve ad alanı bildiriminde adın içeri aktarılan bir ad alanı veya türle ilişkilendirilmesini sağlayan bir extern_alias_directive veya using_alias_directive varsa,I
o ad alanı veya türe başvurur. - Aksi takdirde, ad alanı bildiriminin using_namespace_directivetarafından içeri aktarılan ad alanları ad
I
vex
tür parametrelerine sahip tam olarak bir tür içeriyorsa,R₀
verilen tür bağımsız değişkenleriyle oluşturduğunuz türe başvurur. - Aksi takdirde, ad alanı bildiriminin using_namespace_directivetarafından içeri aktarılan ad alanları ad
I
vex
tür parametrelerine sahip birden fazla tür içeriyorsa, namespace_or_type_name belirsizdir ve derleme zamanı hatası oluşur.
- Eğer
- Eğer
- Aksi takdirde, namespace_or_type_name tanımsız olur ve derleme zamanı hatası oluşur.
- Eğer
R₀
başarılı bir şekilde çözümlendiyse, namespace_or_type_name son kısmı da çözülür. Son dil bilgisi parçası, başvuruda bulunan ad alanını veya türünü daha da çözümleyen k ≥ 0
tekrarları içerir.
Eğer k
sıfırsa, yani sondaki bir bölüm yoksa, namespace_or_type_nameR₀
olarak çözülür.
Aksi takdirde her yineleme aşağıdaki biçimlerden birine sahip olur:
.I
.I<A₁, ..., Aₓ>
burada I
ve A
x
yukarıdaki gibi tanımlanır.
Her yineleme n
için, 1 ≤ n ≤ k
olduğunda çözümü Rₙ
; Rₚ
öğesini içerir, p = n - 1
olduğunda; önceki yinelemenin çözümü aşağıdaki gibi belirlenir:
-
x
sıfır ise veRₚ
bir ad alanına başvuruyorsa veRₚ
içindeI
adlı iç içe bir ad alanı içeriyorsa, o zamanRₙ
bu iç içe ad alanına başvurur. - Aksi takdirde, eğer
Rₚ
bir ad alanına başvuruyorsa veRₚ
adlıI
olan vex
tür parametrelerine sahip erişilebilir bir tür içeriyorsa,Rₙ
verilen tür bağımsız değişkenleriyle birlikte bu türe başvurur. - Aksi takdirde,
Rₚ
, bir (muhtemelen oluşturulmuş) sınıf veya yapı türüne başvuruyorsa veRₚ
ya da onun veya temel sınıflarından birinin, adıI
vex
tür parametrelerine sahip iç içe erişilebilir bir tür içeriyorsa,Rₙ
, verilen tür bağımsız değişkenleriyle oluşturulmuş bu türe başvurur. Birden fazla tür varsa, daha fazla türetilmiş tür içinde bildirilen tür seçilir.Not: Bir tür
T.I
içinT
'in anlamı,T
temel sınıf belirtimini çözümlemenin bir parçası olarak belirlenirse,T
'ün doğrudan temel sınıfıobject
olarak kabul edilir (§15.2.4.2). dipnot - Aksi takdirde , namespace_or_type_name geçersizdir ve derleme zamanı hatası oluşur.
namespace_or_type_name çözümlemesi, son yinelemenin çözümüdür. Rₖ
Bir namespace_or_type_name, yalnızca belirli koşullar altında bir statik sınıfa (§15.2.2.4) atıfta bulunabilir.
-
namespace_or_type_name şunun içindedir: bir
T
formundaT.I
veya -
namespace_or_type_name,
T
(§12.8.18) şeklindeki ifadede olantypeof(T)
'dur.
7.8.2 Nitelenmemiş adlar
Her ad alanı bildirimi ve tür bildirimi aşağıdaki gibi nitelenmemiş bir ada sahiptir:
- Ad alanı bildirimi için nitelenmemiş ad, bildirimde qualified_identifier olarak belirtilen addır.
- type_parameter_list'e sahip olmayan bir tür bildirimi için, nitelenmemiş ad, bildirimde belirtilen tanımlayıcıdır.
- K türü parametrelerine sahip bir tür bildirimi için, nitelenmemiş ad, bildirimde belirtilen tanımlayıcı ve ardından K türü parametreleri için generic_dimension_specifier (§12.8.18) olur.
7.8.3 Tam nitelikli adlar
Her ad alanı ve tür bildirimi, programdaki diğer tüm ad alanı veya tür bildirimini benzersiz olarak tanımlayan tam bir ada sahiptir. Adı nitelenmemiş bir ad alanı veya tür bildiriminin tam nitelikli adı, N
aşağıdaki şekilde belirlenir:
- Genel ad alanının bir üyesiyse
N
, tam adı olurN
. - Aksi takdirde, tam adı
S.N
şeklindedir; buradaS
,N
ad alanı veya tür bildiriminin tam adı içinde bildirilmiştir.
Başka bir deyişle, N
'nin tam nitelikli adı, genel ad alanından başlayarak generic_dimension_specifier ve tanımlayıcıların N
'e götüren tam hiyerarşik yoludur. Bir ad alanının veya türün her üyesi benzersiz bir ada sahip olduğundan, ad alanı veya tür bildiriminin tam nitelikli adı her zaman benzersizdir. Aynı tam adın iki ayrı varliğe başvurması bir derleme zamanı hatasıdır. Özellikle:
- Hem ad alanı bildirimi hem de tür bildiriminin aynı tam ada sahip olması yanlış bir durumdur.
- İki farklı tür bildiriminin aynı tam ada sahip olması bir hatadır (örneğin, hem yapı hem de sınıf bildirimi aynı tam ada sahipse).
- Kısmi değiştiricisi olmayan bir tür bildiriminin, başka bir tür bildirimiyle (§15.2.7) aynı tam ada sahip olması hatadır.
Örnek: Aşağıdaki örnekte, ilişkili tam adlarıyla birlikte çeşitli ad alanı ve tür bildirimleri gösterilmektedir.
class A {} // A namespace X // X { class B // X.B { class C {} // X.B.C } namespace Y // X.Y { class D {} // X.Y.D } } namespace X.Y // X.Y { class E {} // X.Y.E class G<T> // X.Y.G<> { class H {} // X.Y.G<>.H } class G<S,T> // X.Y.G<,> { class H<U> {} // X.Y.G<,>.H<> } }
son örnek
7.9 Otomatik bellek yönetimi
C#, geliştiricilerin nesneler tarafından işgal edilen belleği manuel olarak ayırma ve boşaltma zorunluluğunu ortadan kaldıran otomatik bellek yönetimini kullanır. Otomatik bellek yönetimi ilkeleri bir çöp toplayıcı tarafından uygulanır. Bir nesnenin bellek yönetimi yaşam döngüsü aşağıdaki gibidir:
- Nesne oluşturulduğunda, bu nesne için bellek ayrılır, oluşturucu çalıştırılır ve nesne canlı olarak kabul edilir.
- Sonlandırıcıların çalıştırılması dışında, nesneye veya örnek alanlarından herhangi birine yürütmenin herhangi bir olası devamı tarafından erişilemiyorsa, nesne artık kullanımda kabul edilmez ve sonlandırma için uygun hale gelir.
Not: C# derleyicisi ve çöp toplayıcısı, gelecekte bir nesneye hangi başvuruların kullanılabileceğini belirlemek için kodu analiz etmeyi seçebilir. Örneğin, kapsamdaki bir yerel değişken bir nesneye yapılan tek başvuruysa ancak bu yerel değişkenin, yordamdaki mevcut yürütme noktasından sonra, yürütmenin hiçbir olası devamında kullanılmaması durumunda, çöp toplama işlemi nesneyi artık kullanımda değil olarak değerlendirebilir (ancak bunu yapması zorunlu değildir). dipnot
- Nesne sonlandırma için uygun olduğunda, daha sonra belirtilmeyen bir zamanda nesne için sonlandırıcı (§15.13) (varsa) çalıştırılır. Normal koşullarda nesnenin sonlandırıcısı yalnızca bir kez çalıştırılır, ancak uygulama tanımlı API'ler bu davranışın geçersiz kılınmasına izin verebilir.
- Bir nesnenin sonlandırıcısı çalıştırıldıktan sonra, sonlandırıcıların çalıştırılması da dahil olmak üzere herhangi bir olası yürütme devamı ile nesneye veya örnek alanlarından herhangi birine erişilemiyorsa, nesne erişilemez olarak kabul edilir ve nesne koleksiyon için uygun hale gelir.
Not: Daha önce erişilemeyen bir nesne, sonlandırıcısı nedeniyle yeniden erişilebilir hale gelebilir. Bunun bir örneği aşağıda verilmiştir. dipnot
- Son olarak, nesne toplama için uygun hale geldikten sonra, atık toplayıcı bu nesneyle ilişkili belleği serbest bırakır.
Atık toplayıcı, nesne kullanımı hakkındaki bilgileri korur ve bellekte yeni oluşturulan bir nesneyi nerede bulacağı, bir nesneyi ne zaman yeniden konumlandıracağı ve bir nesnenin artık kullanımda olmadığı veya erişilemeyeceği gibi bellek yönetimi kararları almak için bu bilgileri kullanır.
Bir çöp toplayıcının varlığını varsayarken diğer diller gibi C# da atık toplayıcının çok çeşitli bellek yönetimi ilkeleri uygulayabilmesi için tasarlanmıştır. C# ne bu yayılma alanında bir zaman kısıtlamasını ne de sonlandırıcıların çalıştırılma sırasını belirtir. Sonlandırıcıların uygulama sonlandırmanın bir parçası olarak çalıştırılıp çalıştırılmayacağı uygulama tanımlıdır (§7.2).
Atık toplayıcının davranışı, sınıfındaki System.GC
statik yöntemler aracılığıyla bir dereceye kadar denetlenebilir. Bu sınıf, bir koleksiyonun gerçekleşmesini istemek, sonlandırıcıların çalıştırılmasını (veya çalıştırılmaması) vb. istemek için kullanılabilir.
Örnek: Atık toplayıcının nesneleri ne zaman toplayıp sonlandırıcıları çalıştıracaklarına karar verirken geniş enleme izin verildiğinden, uyumlu bir uygulama aşağıdaki kodla gösterilenden farklı bir çıkış üretebilir. Program
class A { ~A() { Console.WriteLine("Finalize instance of A"); } } class B { object Ref; public B(object o) { Ref = o; } ~B() { Console.WriteLine("Finalize instance of B"); } } class Test { static void Main() { B b = new B(new A()); b = null; GC.Collect(); GC.WaitForPendingFinalizers(); } }
'ın bir instance'ını ve class 'ın bir instance'ını oluşturur. Bu nesneler, değişkenine b
değerinull
atandığında çöp toplama için uygun hale gelir çünkü bu sürenin ardından kullanıcı tarafından yazılan herhangi bir kodun bunlara erişmesi mümkün değildir. Çıkış şu iki durumdan biri olabilir:Finalize instance of A Finalize instance of B
veya
Finalize instance of B Finalize instance of A
çünkü dil, nesnelerin atık toplanma sırasına hiçbir kısıtlama getirmez.
Küçük durumlarda , "sonlandırma için uygun" ile "koleksiyon için uygun" arasındaki ayrım önemli olabilir. Örneğin,
class A { ~A() { Console.WriteLine("Finalize instance of A"); } public void F() { Console.WriteLine("A.F"); Test.RefA = this; } } class B { public A Ref; ~B() { Console.WriteLine("Finalize instance of B"); Ref.F(); } } class Test { public static A RefA; public static B RefB; static void Main() { RefB = new B(); RefA = new A(); RefB.Ref = RefA; RefB = null; RefA = null; // A and B now eligible for finalization GC.Collect(); GC.WaitForPendingFinalizers(); // B now eligible for collection, but A is not if (RefA != null) { Console.WriteLine("RefA is not null"); } } }
Yukarıdaki programda, çöp toplayıcı
A
'ın sonlandırıcısınıB
'in sonlandırıcısından önce çalıştırmayı seçerse, bu programın çıktısı şu olabilir:Finalize instance of A Finalize instance of B A.F RefA is not null
örneğinin
A
kullanımda olmamasına veA
'in sonlandırıcısının çalıştırılmasına rağmen,A
yöntemlerinin (bu örnekte,F
) başka bir sonlandırıcıdan çağrılabilmesi hala mümkündür. Ayrıca, sonlandırıcının çalıştırılmasının bir nesnenin ana hat programından yeniden kullanılabilir duruma gelmesine neden olabileceğini unutmayın. Bu durumda,B
'nin sonlandırıcısının koşulması, daha önce kullanımda olmayan birA
örneğinin canlı referanstanTest.RefA
erişilebilir olmasına neden oldu. ÇağrıWaitForPendingFinalizers
'den sonraB
örneği derleme için uygundur, ancakA
referansından dolayıTest.RefA
örneği uygun değildir.son örnek
7.10 Yürütme sırası
Bir C# programının yürütülmesi, yürütülen her iş parçacığının yan etkilerinin kritik yürütme noktalarında korunmasını sağlar. Yan etki , geçici bir alanın okunması veya yazılması, geçici olmayan bir değişkene yazma, dış kaynağa yazma ve özel durum oluşturma olarak tanımlanır. Bu yan etkilerin sırasının korunacağı kritik yürütme noktaları geçici alanlara (§15.5.4), deyimlere (§13.13) ve iş parçacığı oluşturma ve sonlandırmaya yönelik başvurulardır. lock
Yürütme ortamı, aşağıdaki kısıtlamalara tabi olarak bir C# programının yürütme sırasını değiştirebilir:
- Veri bağımlılığı bir işletim akışı içinde korunur. Yani, her değişkenin değeri, iş parçacığındaki tüm deyimler özgün program sırasına göre yürütülür gibi hesaplanır.
- Başlatma sıralama kuralları korunur (§15.5.5, §15.5.6).
- Yan etkilerin sıralaması, uçucu okuma ve yazma işlemlerine (§15.5.4) göre korunur. Ayrıca, yürütme ortamı bir ifadenin değerinin kullanılmadığını ve gerekli yan etkilerin üretilmediğini (bir yöntemi çağırmanın veya geçici bir alana erişmenin neden olduğu herhangi bir etki de dahil) ortaya çıkarabiliyorsa ifadenin bir bölümünü değerlendirmeye gerek yoktur. Program yürütme eşzamansız bir olay (başka bir iş parçacığı tarafından oluşan özel durum gibi) tarafından kesildiğinde, gözlemlenebilir yan etkilerin aslında program sırasıyla görünür olduğu garanti edilmez.
ECMA C# draft specification