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
Mainolacaktı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ü
asyncveyaSystem.Threading.Tasks.TaskolduğundaSystem.Threading.Tasks.Task<int>değiştiricisine sahip olabilir. - Dönüş türü , ,
voidintveyaSystem.Threading.Tasks.Taskolmalı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
asyncgiriş noktası olarak nitelenebilmesi için yukarıda belirtilen iki dönüş türünden tam olarak birine sahip olması gerekir. Birasync voidyöntem veya farklı bir beklenebilir tür döndüren,asyncveyaValueTaskgibi 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
Mainaynıdır - Yöntemin
Maindönüş türü iseSystem.Threading.Tasks.Task, sentezlenen yöntemin dönüş türü şudur:void - Yöntemin
Maindö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
Mainyönteminin böyle bir parametresi varsa,string[]parametre değerini bağımsız değişken olarak geçirecek şekildeMainyöntemini çağırır. -
MainYö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
Mainyöntemi için, dönüş türüSystem.Threading.Tasks.Task<int>olan görev başarıyla tamamlanırsa,inttarafı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şlatmadan önce konak ortamı tarafından uygulama tanımlı değerler verilen uygulama parametresis olarak adlandırılan dizelere null 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
Denetimin yürütme ortamına döndürülmesi , uygulama sonlandırma olarak bilinir.
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 (§22.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 (§19), numaralandırmaları (§20) ve temsilcileri (§21) 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, yapı veya arabirim, sınıf, yapı veya arabirimle 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ı
valueparametre 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.22.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
yvarsayı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ı (§20.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.CustomerveMegacorp.Data.Orderolmak ü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
FveGyöntemleri, adidış blokta bildirildiği ve iç blokta yeniden bildirilemeyeceği için bir derleme-zamanı hatasına neden olur. Ancak,HveIyöntemleri geçerlidir çünkü ikiiayrı 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 üyelerivardı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 (§19.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.Arraydevralı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 (Invoke) sahip adlı bir yöntem içerir. Bu yöntemin çağrılması, aynı temsilci örneğindeki bir temsilci çağrısıyla (§21.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
publicdeğiştirici ekleyerek seçilen Genel. Sezgisel anlamıpublic"erişim sınırlı değildir". - Korumalı, üye bildirimine bir
protecteddeğiştirici ekleyerek seçilir. Sezgisel anlamıprotected"erişim, içeren sınıf veya arabirim ya da içeren türden türetilen sınıflar ya da arabirimlerle sınırlıdır". - Üye bildirimine bir
internaldeğ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
protectedhem deinternaldeğiştiricileri eklenerek seçilir.protected internalifadesinin sezgisel anlamı, "hem bu derlemede hem de içeren sınıftan türetilen türlerde erişilebilir" şeklindedir. - Üye bildirimine bir
privateveprotecteddeğ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
privatedeğ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
publicbildirilmiş 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
publicveyainternalolabilir ve varsayılan olarakinternalbildirilen erişim düzeyine sahiptir. - Sınıf üyeleri izin verilen türlerden herhangi birine sahip olabilir ve varsayılan olarak
privatebildirilen 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
publicveyainternalbildirilen erişilebilirlik içerebilir. dipnot - Yapı üyeleri,
public,internalveyaprivateolarak bildirilen erişilebilirliğe sahip olabilir ve varsayılan olarakprivateerişilebilirlikte bulunur, çünkü yapılar örtük olarak mühürlenmiştir. Birstructolarak tanıtılan yapı üyeleri (yani bu yapı tarafından devralınmamış olanlar)protected,protected internalveyaprivate protectedbildirilmiş erişilebilirliğe sahip olamaz.Not: Bir yapının üyesi olarak bildirilen bir tür,
public,internalveyaprivateolarak bildirilen erişilebilirliğe sahip olabilirken, bir ad alanının üyesi olarak bildirilen bir tür yalnızcapublicveyainternalolarak bildirilen erişilebilirliğe sahip olabilir. dipnot - Arabirim üyeleri
publicbildirilen 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,Tetki alanının erişilebilirliği,P'nin program metni veP'e başvuran herhangi bir programdır. - Bildirilen erişilebilirliği
Tiç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ğipublicise,M'nin erişilebilirlik etki alanıT'ün erişilebilirlik etki alanıdır. -
Mbildirilen erişilebilirlikprotected internalise,DPprogram metni ileTdışında bildirilenPtüründen türetilen herhangi bir program metninin birleşimi olsun.Merişilebilirlik etki alanı,Terişilebilirlik etki alanı ileD'nin kesişimidir. - **
Verilen
Merişilebilirliğiprivate protectedise,D;PveTprogram metinlerinin veTtüründen türetilmiş herhangi bir türün kesişimi olsun.Merişilebilirlik etki alanı,Terişilebilirlik etki alanı ileD'nin kesişimidir. Möğesinin bildirilen erişilebilirliğiprotectedise,DöğesininTveT'dan türetilen herhangi bir türün program metninin birleşimi olması sağlansın.Merişilebilirlik etki alanı,Terişilebilirlik etki alanı ileD'nin kesişimidir.- Eğer
M'ın bildirilen erişilebilirliğiinternalise,M'ın erişilebilirlik etki alanı,T'ın erişilebilirlik etki alanı ileP'ün program metninin kesişimidir. - Bir
M'nin bildirilen erişilebilirliğiprivateise,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
Merişildiğinde, erişime izin verildiğinden emin olmak için aşağıdaki adımlar değerlendirilir:
- İlk olarak,
Mbir 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
Mpublicise, erişime izin verilir.- Aksi takdirde,
Mprotected internalise, erişim bildirildiğiMprogram 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,
Mprotectedise, erişime,Msınıfı içinde gerçekleşiyorsa veyaMsı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,
Minternalise,Mbildirildiği program içinde gerçekleşirse erişime izin verilir.- Aksi takdirde,
Mprivateise,Mbildirilmiş 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:
AveA.Xerişilebilirlik etki alanı sınırsızdır.A.Y,B,B.X,B.Y,B.C,B.C.XveB.C.Yerişilebilirlik etki alanı, içeren programın program metnidir.- erişilebilirlik etki alanı
A.Z, program metnidirA.B.ZveB.Döğelerinin erişilebilirlik etki alanı,Bprogram metni olup, bu metinB.CveB.Dprogram metinlerini de içerir.- erişilebilirlik etki alanı
B.C.Z, program metnidirB.C.B.D.XveB.D.Yöğelerinin erişilebilirlik etki alanı,Bprogram metni olup, bu metinB.CveB.Dprogram 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.Xdışı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 } }
Bsınıfı,xsınıfından özel üyeA'yi devralır. Üye özel olduğundan, yalnızca class_body içindeAerişilebilir. Bu nedenle, erişimib.xyöntemindeA.Fbaşarılı olur, ancak yöntemindeB.Fbaş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. veya protected erişimi ile private protected tanımlanan örnek arabirimi üyelerine, bu arabirimi uygulayan veya bu arabirimi uygulayan bir class veya'dan struct erişilemez; bunlara yalnızca türetilmiş arabirimlerden erişilebilir. Ancak ve class türleri, struct uyguladığı bir arabirimde bildirilen geçersiz kılınmış protected örnek üyelerini tanımlayabilir.
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; buradaEtürüTya daT'den türetilmiş bir sınıf olduğunda,TiseDsı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 daxveAörnekleri aracılığıylaB'e erişim mümkündür, çünkü erişim,AveyaA'dan türetilmiş bir sınıfın örneği üzerinden gerçekleşir. Ancak,Biçinde birxörneği üzerindenA'e erişmek mümkün değildir, çünküAB'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,Dsı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 {...}
Bsınıfı,Aen azBkadar 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
HyöntemiB, dönüş türüAen 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ıylakarakterize 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
paramsparametre değiştiricilerini ya da parametrelerinthisgerekli 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, outve ref imzanın bir parçası olarak kabul edilir ve birbiriyle eşleşmez.
Not: Bu kısıtlama, C# programlarının yalnızca ,
inveoutiçinde farklı yöntemleri tanımlamanın bir yolunu sağlamayan bir platformdarefçalıştırılacak şekilde kolayca çevrilebilmesini sağlamaktır. 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,outverefparametre 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,outverefile farklılık gösterdiği için aynı arabirim içinde bildirilemez. Ayrıca, dönüş türünün ve değiştiricininparamsimzanın parçası olmadığını unutmayın, bu nedenle yalnızca dönüş türüne veya değiştiricinin eklenmesine veya dışlanmasınaparamsbağ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ı
Nolan 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.
interface_declaration bir type_parameter_list (§19.2) tarafından bildirilen tür parametresinin kapsamı, bu interface_declaration interface_base, type_parameter_constraints_clauses ve interface_body.
delegate_declaration type_parameter_list (§21.2) tarafından bildirilen tür parametresinin kapsamı, bu delegate_declaration return_type, parameter_list ve type_parameter_constraints_clause'leridir.
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.
bir enum_member_declaration (§20.4) tarafından bildirilen bir üyenin kapsamı, bildirimin gerçekleştiği enum_body .
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.21) içinde bildirilen parametrenin kapsamı, bu lambda_expression lambda_expression_body.
anonymous_method_expression bildirilen parametrenin kapsamı (§12.21), bu anonymous_method_expressionbloğ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ı
switchswitch_block'tır (§13.8.3).Bir for_initializer bildiriminde (§13.9.4) tanımlanan yerel değişkenin kapsamı,
fordeyiminin 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.Gyönteminde,jbildirimi içinjbaşlatıcıda kullanılması geçerlidir çünkü kullanım bildirimciden önce gelmez.Hyö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ı
Aifade bağlamında yerel değişkenA'e, tür bağlamında ise sınıfaAbaş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; } }
Fyönteminde, örnek değişkeni, yerel değişkenitarafından gizlenir, ancakGyönteminin içinde,iyine de örnek değişkene başvurur. yerel işlevM1içinde,float ihemen dışındakiigizler. lambda parametresii, lambda gövdesininfloat iiç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),Fiç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, yapı veya arabirimde 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, yapı veya arabirimde tanıtılan bir yöntem, aynı ada sahip yöntem dışı tüm temel sınıf üyelerini ve aynı imzaya (§7.6) sahip tüm temel sınıf yöntemlerini gizler.
- Bir sınıf, yapı veya arabirimde tanıtılan bir dizin oluşturucu, aynı imzaya (§7.6) sahip tüm temel tür 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 }
FbildirimiDerivediç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 birFyö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() {} }
newmodifikatörü,Fiç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'dekiDerivedtanı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:
II<A₁, ..., Aₓ>
nerede:
-
Itek bir tanımlayıcıdır; ve -
<A₁, ..., Aₓ>bir type_argument_list olduğunda, hiçbir type_argument_list belirtilmezse,xsıfır olarak kabul edilir.
R₀ aşağıdaki gibi belirlenir:
-
xsı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 , namespace_or_type_name bir tür bildirimi içinde görünürse, her örnek türü
Tiçin (§15.3.2), bu tür bildiriminin örnek türüyle başlayıp her bir kapsayan sınıfın, yapının veya arabirim bildiriminin örnek türüyle (varsa) devam edin:- Eğer
xsıfırsa veTbildirimiIadı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
Tveya temel türlerinden herhangi biri adIvextü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. Hiçbir tür diğerlerinden daha fazla türetilmemişse bu bir derleyici hatasıdır.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ı
Niç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
xsıfırsa veI,Niçindeki bir ad alanının adıysa:- "Eğer namespace_or_type_name oluştuğu yer,
Niç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çindeIadlıNad alanına başvurur.
- "Eğer namespace_or_type_name oluştuğu yer,
- Aksi takdirde,
NisimIvextür parametrelerine sahip erişilebilir bir tür içeriyorsa:-
xsıfır ise ve namespace_or_type_name oluştuğu konumNiç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,Ibelirsizdir 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
Nbir ad alanı bildirimiyle çevreleniyorsa:- Eğer
xsı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,Io ad alanı veya türe başvurur. - Aksi takdirde, ad alanı bildiriminin using_namespace_directivetarafından içeri aktarılan ad alanları ad
Ivextü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
Ivextü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 Ive Ax 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:
-
xsıfır ise veRₚbir ad alanına başvuruyorsa veRₚiçindeIadlı 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ıIolan vextü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, (büyük olasılıkla oluşturulmuş) bir sınıfa, yapıya veya arabirim türüne başvuruyorsa
RₚveRₚya da temel türlerinden herhangi biri adIvextü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. Hiçbir tür diğerlerinden daha fazla türetilmemişse bu bir derleyici hatasıdır.Not: Bir tür
T.IiçinT'in anlamı,Ttemel sınıf belirtimini çözümlemenin bir parçası olarak belirlenirse,T'ün doğrudan temel sınıfıobjectolarak 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
TformundaT.Iveya -
namespace_or_type_name,
T(§12.8.18) şeklindeki ifadede olantypeof(T)'dur.
Örnek:
interface A { class NestedClass { public static void M() {} } } interface B { class NestedClass { public static void M() {} } } interface C : A, B { public void Test() { NestedClass.M(); } // ambiguity between // A.NestedClass and B.NestedClass }Yukarıdaki örnekte, ve arasında
NestedClass.M()C.Test()çağrısıB.NestedClass.M()A.NestedClass.M()belirsizdir çünkü hiçbiri diğerinden daha türetilmiş değildir. Belirsizliği çözmek içinA.NestedClass.M()veyaB.NestedClass.M()için açık bir başvuru gereklidir.son örnek
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,Nad 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.GCstatik 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 bdeğerinullatandığı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 Bveya
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
Akullanımda olmamasına veA'in sonlandırıcısının çalıştırılmasına rağmen,Ayö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.RefAerişilebilir olmasına neden oldu. ÇağrıWaitForPendingFinalizers'den sonraBörneği derleme için uygundur, ancakAreferansı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