7 Temel kavramlar

7.1 Uygulama başlatma ve sonlandırma

7.1.1 Genel

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.

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 çalıştırması, aşağıdaki yollardan herhangi birinde belirtilen aday giriş noktalarından derleme zamanında seçilen bir giriş noktası çağrılarak başlatılır:

  1. Açıkça, uygun özelliklere sahip bir yöntem bildirerek (§7.1.2).
  2. Örtük olarak, üst düzey deyimleri (§7.1.3) kullanarak.
  3. Uygulama tanımlı, giriş noktasını (§7.1.4) belirtmek için bu belirtim dışında bir mekanizma kullanılarak tanımlanır.

Not: En üst düzey deyim adayları (§7.1.3) dışında tüm aday giriş noktaları standart yöntemlerdir; bir aday veya seçilen giriş noktası olması, bu yöntemlerin normal şekilde çağrılmasını engellemez. dipnot

Aday giriş noktası yoksa bu bir derleme zamanı hatasıdır.

Aksi takdirde, §7.1.5'teki işlemi izleyen giriş noktası olarak derleme zamanında bir aday seçilir.

Uygulama, seçilen giriş noktası §7.1.6'da açıklandığı gibi çağrılarak çalıştırılır.

Ana bilgisayar ortamına başarı veya başarısızlık iletişimine izin vermek olan sonlandırma durum kodu, giriş noktası çağrısının (§7.1.6) sonucuna göre belirlenir.

7.1.2 Adlandırılmış giriş noktaları

Bir yöntem, aşağıdaki gereksinimleri karşılayarak bir canditate giriş noktası olarak nitelenir:

  • İ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.
  • Dönüş türü , , voidintveya System.Threading.Tasks.TaskolmalıdırSystem.Threading.Tasks.Task<int>.
  • Değiştiriciye async yalnızca yöntemin dönüş türü veya System.Threading.Tasks.Task<int>ise System.Threading.Tasks.Task sahip olabilir.
  • Uygulama bildirimi olmadan isteğe bağlı bir kısmi 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.

Bir yöntemin bildirilen erişilebilirliği (§7.4.2), aday giriş noktası olarak niteleme amacıyla yoksayılır. Uygulama başlangıcında, belirtilen erişilebilirliği ne olursa olsun seçili giriş noktası çağrılır. Ancak, seçilen aday giriş noktası uygulama başlangıcından sonra çağrılırsa, bildirilen tüm erişilebilirlikler uygulanmaya devam eder.

Not: Buradaki gereksinimler sınıf üyesi olması gerektiğini belirtmez Main , bir yapı üyesi olabilir. dipnot

7.1.3 Üst düzey deyimleri kullanma

Bir uygulamadaki tek bir derleme birimi (§14.2) en üst düzey deyimler olarak adlandırılan bir statement_list içerebilir. Üst düzey deyimlerin anlamı, genel ad alanında aşağıdakileri bildirmekle anlamsal olarak eşdeğerdir:

partial class Program
{
    static «AsyncAndReturnType» «Main»(string[] args)
    {
        «statement_list»
    }
}

sınıfıProgram, uygulama içindeki diğer kısmi sınıf bildirimleriyle birleştirilen kısmi tür bildirimidir Program (§15.2.7).

Not: Bu, üst düzey bir deyimin genel ad alanında sınıfında Program tanımlanan statik bir yöntemin gövdesindeki bir deyimle aynı erişim haklarına sahip olduğu anlamına gelir. dipnot

Yöntem adı «Main» , yalnızca yürütme ortamı tarafından doğrudan erişilebilen ve uygulama içinden doğrudan başvurulamayan, belirtilmemiş bir uygulama sağlanan adı için yer tutucudur. Ayrıca, kullanılan adın C# yöntemi adı olarak geçerli olması gerekmez.

Not: Ancak kullanılan adın gösterimi, özniteliğini kullanan bir string yöntemi çağırırsa (§23.5.6.4) bir üst düzey deyiminin CallerMemberName yürütülmesi sırasında olarak elde edilebilir. dipnot

«statement_list», derleme birimininstatement_list için bir yer tutucudur.

parametresi args , üst düzey deyimlerin kapsamındadır ve başka bir şekilde değildir. Normal ad çakışması/gölgeleme kuralları uygulanır. Bu parametre uygulama parametrelerini (§7.1.6) alır.

Zaman uyumsuz işlemler, adlandırılmış bir zaman uyumsuz giriş noktası yöntemi içindeki deyimlerde izin verilen dereceye kadar üst düzey deyimlerde izin verilir.

Yöntem imzasında yer tutucunun «AsyncAndReturnType» değiştirilmesi, üst düzey deyimlerin içeriğine göre aşağıdaki gibi belirlenir:

Üst düzey deyimler Oluşturulan imza
Hayır await veya return değerle static void «Main»(string[] args)
return yalnızca değer içeren static int «Main»(string[] args)
await sadece static async Task «Main»(string[] args)
await ve return değeriyle static async Task<int> «Main»(string[] args)

Oluşturulan bu imzalar adlandırılmış giriş noktaları (§7.1.2) gereksinimlerini karşılar ve bu nedenle «Main» bir aday giriş noktasıdır.

Not: Bu imzalar bildirilen erişilebilirlik içermez (§7.4.2). Ancak bir uygulama, bildirilen erişilebilirliği içerebilir; giriş noktası yöntemlerinde (§7.1.2) erişilebilirlik yoksayıldığı için yöntem yine de eş anlamlı olarak eşdeğer olacaktır.

7.1.4 Dış tanımlı giriş noktası

Bir uygulama, aday giriş noktası belirtmek için bu belirtim dışında bir mekanizma sağlayabilir.

Bu mekanizma program içinde bir tür tanımlarsa, aday giriş noktası adlandırılmış giriş noktaları (§7.1.2) için belirtildiği şekilde belirlenir.

Bu mekanizma program içinde bir yöntem tanımlarsa, yöntemin herhangi bir adı olabilir, ancak aksi takdirde adlandırılmış giriş noktaları (§7.1.2) için belirtilen gereksinimleri karşılaması gerekir.

Dış mekanizma yalnızca tek bir aday giriş noktası belirtebilir.

Dış mekanizma tarafından belirtilen bir aday giriş noktası, giriş noktası seçiminde önceliklidir (§7.1.5).

7.1.5 Giriş noktası seçimi

Aday giriş noktası yoksa bu bir derleme zamanı hatasıdır.

Aksi takdirde adaylardan giriş noktası seçilir:

  • Adaylardan biri bir dış mekanizma (§7.1.4) tarafından belirtilirse, giriş noktası olarak seçilir;
  • Aksi takdirde, adaylardan biri en üst düzey deyimlerle tanımlanır (§7.1.3) giriş noktası olarak seçilir;
  • Yoksa:
    • Adaylardan herhangi birinin dönüş türü veya dönüş türüne intvoidSystem.Threading.Tasks.TaskSystem.Threading.Tasks.Task<int> sahip olan adaylar aday havuzundan çıkarılırsa.
    • Kalan tek bir aday varsa, giriş noktası olarak seçilir.
    • Aksi takdirde giriş noktası belirlenemez ve derleme zamanı hatası bildirilir.

Derleme zamanında seçilen giriş noktası, uygulama başlatma (§7.1.6) kapsamında çalışma zamanında çağrılır.

7.1.6 Giriş noktası çağrısı

Giriş noktası bir parametre bildirirse, uygulama bu parametrenin ilk değeri olarak bir dize dizisine null olmayan bir başvuru sağlar. Bu dizi, uygulama başlatmadan önce konak ortamı tarafından uygulama tanımlı değerler verilen , uygulama parametresis olarak adlandırılan sıfır veya daha fazla dizeye null olmayan başvurulardan oluşacaktı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

Uygulama başlatma ve sonlandırma işlemi, aşağıdaki adımlarla eşdeğerdir:

  • Uygulama çalıştırması şu iki durumdan biri tarafından başlatılır:
    • Dönüş türü void veya ise giriş noktası yöntemini çağırma (§12.8.10) veya int
    • Dönüş türü bir Task türse giriş noktası yöntemini çağırmanın sonucu bekleniyor (§12.9.9).
    • Her iki durumda da, giriş noktası bir bağımsız değişken gerektiriyorsa, uygulama parametresi dizisi değeri olarak sağlanır.

Not: Giriş noktası yöntemini çağırmak, varsa, kapsayan türün statik oluşturucusunun önce yürütülmesine neden olur (§15.12, §16.8.10). dipnot

  • Uygulama sonlandırıldı
    • Çalıştırma bir int değerle sonuçlanırsa sonlandırma durum kodu olarak görev alır;
    • Aksi takdirde, çalıştırma hiçbir dönüş değeriyle sonuçlanırsa sonlandırma durum kodu olur 0;
    • Aksi takdirde, çalıştırma bir özel durum nedeniyle sonlandırılırsa (§22.4), çı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.

Note: .NET Framework uygulaması, henüz çöp toplanmamış tüm nesneleri için sonlandırıcıları (§15.13) çağırmak için her türlü makul çabayı gösterir, böyle bir temizleme gizlenmediği sürece (örneğin, GC.SuppressFinalize kitaplık yöntemine yapılan bir çağrı ile). dipnot

7.2 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.8), 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.5).
  • Aynı ada sahip iki veya daha fazla tür bildirimine ancak aynı bildirim alanında (§7.7.2) farklı tür parametrelerine izin verilir.
  • 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.7.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. §14.3 başına bu, file_scoped_namespace_declaration'leriiçerir.
  • Her bir compilation_unit ve namespace_body bir takma ad bildirim alanı vardır. compilation_unit veya namespace_body her extern_alias_directive ve using_alias_directive diğer ad bildirim alanına (§14.6.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.5). 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 ve parameter_collection) 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 ve parameter_collection) ve type_parameters aracılığıyla bu bildirim alanına eklenir. Bir özellik veya dizin oluşturucu için set and init 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 bildirim alanı ve iç içe yerel değişken bildirim alanı aynı ada sahip öğeler içerdiğinde, iç içe yerel ad kapsamında dış yerel ad iç içe yerel ad tarafından gizlenir (§7.6.1).

    Not: Anonim işlevlerin (§12.22.2) at parametreleri herhangi bir bildirim alanına ad eklemez. dipnot

  • Ü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.23.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şken z , 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.6).
  • 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.Customer ve Megacorp.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 ve G yöntemleri, ad i dış blokta bildirildiği ve iç blokta yeniden bildirilemeyeceği için bir derleme-zamanı hatasına neden olur. Ancak, H ve I yöntemleri geçerlidir çünkü iki i 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.3 Üyeler

7.3.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 üyeye türetilmiş bir türde erişilebilir olmayabilir; örneğin, bildirilen erişilebilirliği (§7.4.2). dipnot

7.3.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.3.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.3.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.3.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.3.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ıftaki object üyeler herhangi bir arabirim türünde (§12.5) üye arama yoluyla kullanılabilir. dipnot

7.3.7 Dizi üyeleri

Bir dizinin üyeleri sınıfından System.Arraydevralınan üyelerdir.

7.3.8 Üye temsilcisi

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.4 Üye erişimi

7.4.1 Genel

Üyelerin bildirimleri, üye erişimi üzerinde denetime izin verir. Üyenin erişilebilirliği, üyenin bildirilen erişilebilirliği (§7.4.2) tarafından oluşturulur ve varsa hemen 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. Erişimin gerçekleştiği metinsel konum üyenin erişilebilirlik etki alanına (§7.4.3) dahil edildiğinde üyeye erişime izin verilir.

7.4.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ç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 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 de internal 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 ve protected 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 veya internal olabilir ve varsayılan olarak internal 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 veya internal bildirilen erişilebilirlik içerebilir. dipnot

  • Yapı üyeleri, public, internal veya private olarak bildirilen erişilebilirliğe sahip olabilir ve varsayılan olarak private erişilebilirlikte bulunur, çünkü yapılar örtük olarak mühürlenmiştir. Bir struct olarak tanıtılan yapı üyeleri (yani bu yapı tarafından devralınmamış olanlar) protected, protected internal veya private protected bildirilmiş erişilebilirliğe sahip olamaz.

    Not: Bir yapının üyesi olarak bildirilen bir tür, public, internal veya private olarak bildirilen erişilebilirliğe sahip olabilirken, bir ad alanının üyesi olarak bildirilen bir tür yalnızca public veya internal olarak bildirilen erişilebilirliğe sahip olabilir. dipnot

  • Arabirim üyeleri public bildirilen erişilebilirliğe sahiptir.
  • Numaralandırma üyeleri örtük olarak erişilebilirlik bildirmiş public . Numaralandırma üyesi bildirimlerinde erişim değiştiricisine izin verilmez.

7.4.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 ve P'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ği public ise, M'nin erişilebilirlik etki alanı T'ün erişilebilirlik etki alanıdır.
  • M bildirilen erişilebilirlik protected internal ise, DP program metni ile T dışında bildirilen P türünden türetilen herhangi bir program metninin birleşimi olsun. M erişilebilirlik etki alanı, T erişilebilirlik etki alanı ile D'nin kesişimidir.
  • ** Verilen M erişilebilirliği private protected ise, D; P ve T program metinlerinin ve T türünden türetilmiş herhangi bir türün kesişimi olsun. M erişilebilirlik etki alanı, T erişilebilirlik etki alanı ile D'nin kesişimidir.
  • M öğesinin bildirilen erişilebilirliği protected ise, D öğesinin T ve T'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ı ile D'nin kesişimidir.
  • Eğer M'ın bildirilen erişilebilirliği internal ise, M'ın erişilebilirlik etki alanı, T'ın erişilebilirlik etki alanı ile P'ün program metninin kesişimidir.
  • Bir M'nin bildirilen erişilebilirliği private 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 Mpublic ise, erişime izin verilir.
  • Aksi takdirde Mprotected internal, erişim, bildirildiği M program içinde gerçekleşirse veya bildirildiği ve türetilmiş sınıf türü (§7.4.4) aracılığıyla gerçekleşen sınıftan türetilen bir sınıf M içinde gerçekleşirse erişime izin verilir.
  • Aksi takdirde, ise Mprotected, erişim, bildirildiği M sınıfın içinde gerçekleşirse veya bildirildiği ve türetilmiş sınıf türü (§7.4.4) aracılığıyla gerçekleşen sınıftan türetilen bir sınıf M içinde gerçekleşirse erişime izin verilir.
  • Aksi takdirde, Minternal ise, M bildirildiği program içinde gerçekleşirse erişime izin verilir.
  • Aksi takdirde, Mprivate 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 ve A.X erişilebilirlik etki alanı sınırsızdır.
  • A.Y, B, B.X, B.Y, B.C, B.C.X ve B.C.Y erişilebilirlik etki alanı, içeren programın program metnidir.
  • erişilebilirlik etki alanı A.Z , program metnidir A.
  • B.Z ve B.D öğelerinin erişilebilirlik etki alanı, B program metni olup, bu metin B.C ve B.D program metinlerini de içerir.
  • erişilebilirlik etki alanı B.C.Z , program metnidir B.C.
  • B.D.X ve B.D.Y öğelerinin erişilebilirlik etki alanı, B program metni olup, bu metin B.C ve B.D program metinlerini de içerir.
  • erişilebilirlik etki alanı B.D.Z , program metnidir B.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üm X ü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.3'te açıklandığı gibi, örnek oluşturucuları, sonlandırıcılar ve statik oluşturucular dışında 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 üye A'yi devralır. Üye özel olduğundan, yalnızca class_body içinde A erişilebilir. Bu nedenle, erişimi b.x yönteminde A.F başarılı olur, ancak yönteminde B.F başarısız olur.

son örnek

7.4.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ıkları bir arabirimde bildirilen örnek üyelerini uygulayabilirprotected.

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 (veya record_class_body) Diçinde öğesine M erişim aşağıdaki formlardan birini alabilir:

  • Nitelenmemiş bir type_name veya primary_expression formu M.
  • biçiminde bir E.M; burada E türü T ya da T'den türetilmiş bir sınıf olduğunda, T ise D sınıfı veya D'den oluşturulmuş bir sınıf türüdür.
  • Bir primary_expression biçiminde base.M.
  • Bir primary_expressionbase[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 da x ve A örnekleri aracılığıyla B'e erişim mümkündür, çünkü erişim, A veya A'dan türetilmiş bir sınıfın örneği üzerinden gerçekleşir. Ancak, B içinde bir x örneği üzerinden A'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.4.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 öğesine C<int>.x üyesine yapılan başvuru, D sınıfı D'den türetilmiş olsa bile geçerlidir. dipnot

7.4.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 az B 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öntemi B , dönüş türü A en az yöntem kadar erişilebilir olmadığından derleme zamanı hatasıyla sonuçlanır.

son örnek

7.5 İ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ı, , paramsveya scoped parametre değiştiricilerini ya da parametrelerin thisgerekli 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. Dizin oluşturucunun imzası özellikle öğe türünü veya değiştiriciyi scoped içermez, en doğru parametre veya değiştirici için belirtilebilen değiştiriciyi ya da parametrelerin params gerekli veya isteğe bağlı olup olmadığını içermezscoped.
  • 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ü veya değiştiriciyi scoped 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 veya değiştirici değildir scoped .
  • 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.

parameter_mode_modifierbir imzanın parçası olarak kabul edilse de, tek bir türde bildirilen üyeler imzada yalnızca bu değiştiriciler tarafından farklılık gösteremez. 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), parameter_mode_modifierimzanın bir parçası olarak kabul edilir ve birbiriyle eşleşmez.

Not: Bu kısıtlama, C# programlarının yalnızca kendi parameter_mode_modifierfarklı yöntemleri tanımlamanın bir yolunu sağlamayan bir platformda ç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(ref readonly int x); // F(ref int) error
    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 parameter_mode_modifier(§15.6.2) bir imzanın parçası olduğunu unutmayın. Bu nedenle, F(int), F(in int), F(out int) , F(ref int)ve F(ref readonly int) tüm benzersiz imzalardır. Ancak, F(in int)imzaları F(out int)yalnızca parameter_mode_modifier'lerinegöre farklılık gösterdiğinden , , F(ref int)ve F(ref readonly int) aynı arabirim içinde bildirilemez. Ayrıca, dönüş türünün ve değiştiricinin params 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ına params bağlı olarak aşırı yükleme yapılamaz. Bu nedenle, yukarıda tanımlanan F(int) ve F(params string[]) yöntemlerinin bildirimleri bir derleme zamanı hatasına neden olur. son örnek

7.6 Kapsamlar

7.6.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, iç içe bir blok içinde yerel değişken veya yerel sabit ile aynı ada sahip bir yerel değişken veya bir kapalı blokta yerel sabit bildirmenin mümkün olmadığı için §7.2 tarafından uygulanan kısıtlamayı kaldırmaz.) Daha sonra dış kapsamdaki adın, iç kapsamın kapsadığı program metninin bölgesinde gizlendiği söylenir ve dış ada erişim yalnızca adın nitelenmesiyle mümkündür.

Not: İç içe tür bildirimlerindeki tür parametreleri gibi, bunu nitelemenin bir yolu olmadığından gizli dış ada iç kapsamdan erişmek mümkün olmayabilir. dipnot

  • Bir namespace_member_declaration (§14.7) tarafından bildirilen ve kapsayan namespace_declaration olmayan bir ad alanı üyesinin kapsamı, program metninin tamamıdır.
  • Tam adı olan bir compilation_unit_body tarafından bildirilen ad alanı üyesinin kapsamı, tam adı N veya ile Nbaşlayan her N ve ardından bir noktadı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'ın N'sini kapsar ve ardından bir nokta gelir. §14.3 başına, file_scoped_namespace_declarationbu kural için eşdeğer namespace_declarations olarak değerlendirilir.
  • bir extern_alias_directive (§14.4) tarafından tanımlanan bir adın kapsamı, hemen compilation_unitveya namespace_bodyiçeren global_using_directive s, using_directive, global_attributes ve compilation_unit_body genişletir. 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 oluştuğu compilation_unit, namespace_body ve file_scoped_namespace_declaration etkiler.
  • Bir global_using_directive tarafından tanımlanan veya içeri aktarılan bir adın kapsamı, programdaki tüm compilation_unit global_attributesvecompilation_unit_bodygenişletilir.
  • bir using_directive (§14.6) tarafından tanımlanan veya içeri aktarılan bir adın kapsamı,using_directive oluştuğu compilation_unit veya namespace_body global_attributes, statement_list ve namespace_member_declaration s'ler ü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.
  • class_declaration bir type_parameter_list (§15.2) tarafından bildirilen tür parametresinin kapsamı, buclass_declaration class_base, type_parameter_constraints_clauses ve class_body (veya record_class_body).

    Not: Sınıfın üyelerinden farklı olarak, bu kapsam türetilmiş sınıflara genişletilmez. dipnot

  • struct_declaration type_parameter_list (§16.2) tarafından bildirilen tür parametresinin kapsamı, bu struct_declaration struct_interfaces, type_parameter_constraints_clauses ve struct_body (veya record_struct_body) değeridir.
  • 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.
  • method_declaration birtype_parameter_list (§15.6.1) tarafından bildirilen tür parametresinin kapsamı, method_declaration veya parametrelerindeki bir öznitelikteki nameof ve ifadelerdir.
  • bir class_member_declaration (§15.3.1) tarafından bildirilen bir üyenin kapsamı, bildirimin gerçekleştiği class_body (veya record_class_body). Ayrıca, bir sınıf üyesinin kapsamı, üyenin erişilebilirlik etki alanına (§7.4.3) dahil edilen türetilmiş sınıfların class_body (veya record_class_body) kapsamına genişletilir.
  • bir struct_member_declaration (§16.3) tarafından bildirilen bir üyenin kapsamı, bildirimin gerçekleştiği struct_body (veya record_struct_body).
  • bir enum_member_declaration (§20.4) tarafından bildirilen bir üyenin kapsamı, bildirimin gerçekleştiği enum_body .
  • bir method_declaration (§15.6) içinde bildirilen bir parametrenin kapsamı, yöntem bildirimindeki veya parametrelerindeki bir öznitelikteki method_declaration ve nameof ifadelerin method_body veya ref_method_body.
  • 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.
  • Atma parametreleri (§12.22.2) dışında, lambda_expression bildirilen parametrenin kapsamı (§12.22) söz konusu lambda_expressionlambda_expression_body ve nameof anonim işlev veya parametrelerindeki bir öznitelikteki ifadelerdir.
  • Atma parametreleri (§12.22.2) dışında, anonymous_method_expression bildirilen parametrenin kapsamı (§12.22) söz konusu anonymous_method_expression ve nameof anonim işlev veya parametrelerindeki bir öznitelikteki ifadelerin 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ı switchswitch_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 önce i'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çin j 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şken A'e, tür bağlamında ise sınıfa A başvurmak için kullanılır.

dipnot

§7.1.3'te açıklandığı gibi, en üst düzey kaynak belirteçleri oluşturulan giriş noktası yöntemiyle çevrelenir.

Basit ad değerlendirmesi amacıyla, genel ad alanına ulaşıldıktan sonra, ilk olarak, oluşturulan giriş noktası yöntemi içinde adı değerlendirme girişiminde bulunulup ancak bu girişim başarısız olursa, gerçekleştirilen genel ad alanı bildirimi içindeki değerlendirme yapılır.

Bu, genel ad alanı içinde bildirilen ad alanlarının ve türlerin ad gölgelenmesine ve içeri aktarılan adların gölgelenmesine yol açabilir.

Basit ad değerlendirmesi üst düzey deyimlerin dışında gerçekleşirse ve değerlendirme en üst düzey bir yerel değişken veya işlev verirse, derleme zamanı hatası sonuçları verir.

7.6.2 Adı gizleme

7.6.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.6.2.2 İç içe yerleştirme aracılığıyla gizleniyor

İç 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şken i, yerel değişken i tarafından gizlenir, ancak G yönteminin içinde, i yine de örnek değişkene başvurur. yerel işlev M1 içinde, float i hemen dışındaki i gizler. lambda parametresi i , lambda gövdesinin float 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 edilen Inner'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.6.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.5) 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.5) 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
}

F bildirimi Derived 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, öğesinin sonraki bir sürümünde sınıfının önceki bir sürümünde Base mevcut olmayan bir F yöntem tanıtıldığı için ortaya çıkabilirdi.

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çindeki Derived'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'deki Derived tanımı, F'ten devralınan Base'yi gizler, ancak F'deki yeni Derived özel erişime sahip olduğundan, kapsamı MoreDerived'ya kadar genişletilmez. Bu nedenle, F() içinde MoreDerived.G çağrısı geçerlidir ve Base.F'yi çağırır.

son örnek

7.7 Ad alanı ve tür adları

7.7.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 baştaki bölümü bir qualified_alias_member ise, R₀bunu §14.9.1'de açıklandığı gibi çözümleyerek tanımlanan ad alanı veya türdür.

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 , namespace_or_type_name bir tür bildirimi içinde görünürse, 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ın, yapının veya arabirim bildiriminin örnek türüyle (varsa) devam edin:
    • Eğer x sıfırsa ve T bildirimi I adında bir tür parametresi içeriyorsa, o zaman R₀ 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 ad I ve x 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. 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ı 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 ve I, N içindeki bir ad alanının adıysa:
        • namespace_or_type_name oluştuğu konum için N bir ad alanı bildiriminin içine alınmışsa ve ad alanı bildirimi adı bir ad alanı veya türle ilişkilendiren bir extern_alias_directive veya I içeriyorsa ya da programdaki herhangi N bir ad alanı bildirimi adı bir ad alanı veya türle ilişkilendiren bir I içeriyorsa, ardından namespace_or_type_name belirsiz olur ve derleme zamanı hatası oluşur.
        • Aksi takdirde, R₀ içinde I adlı N ad alanına başvurur.
      • Aksi takdirde, N isim I ve x tür parametrelerine sahip erişilebilir bir tür içeriyorsa:
        • sıfır ise x ve namespace_or_type_name oluştuğu konum için N bir ad alanı bildirimiyle kapatılır ve ad alanı bildirimi adı bir ad alanı veya türle ilişkilendiren bir extern_alias_directive veya I içerir ya da programdaki ad N alanı bildirimi adı bir ad alanı veya türle ilişkilendiren bir I içerir. ardından namespace_or_type_name belirsiz olur 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:
        • Sıfır ise x ve ad alanı bildirimi adı içeri aktarılan ad alanı veya türle ilişkilendiren bir extern_alias_directive veya I içeriyorsa ya da programdaki için N herhangi bir ad alanı bildirimi adı içeri aktarılan ad alanı veya türle ilişkilendiren bir I içerir, ardından R₀ bu ad alanına veya türe başvurur.
        • Aksi takdirde, ad alanı bildiriminin using_namespace_directivetarafından içeri aktarılan ad alanları ve programdaki herhangi bir ad alanı bildiriminin global_using_namespace_directives ve global_using_static_directive'leritarafından içeri aktarılan ad alanları ve tür bildirimleri N , ad I ve x tür parametrelerine sahip tam olarak bir tür içeriyorsa, R₀ verilen tür bağımsız değişkenleriyle birlikte bu türe başvurur.
        • Aksi takdirde, ad alanı bildiriminin using_namespace_directivetarafından içeri aktarılan ad alanları ve programdaki herhangi bir ad alanı bildiriminin global_using_namespace_directives ve global_using_static_directive'leritarafından içeri aktarılan ad alanları ve tür bildirimleri N , ad I ve x tür parametrelerine sahip birden fazla tür içeriyorsa, namespace_or_type_name belirsiz olur ve derleme zamanı hatası oluşur.
    • Aksi takdirde, namespace_or_type_name tanımsız olur ve derleme zamanı hatası oluşur.

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:

  • x sıfır ise ve Rₚ bir ad alanına başvuruyorsa ve Rₚ içinde I adlı iç içe bir ad alanı içeriyorsa, o zaman Rₙ bu iç içe ad alanına başvurur.
  • Aksi takdirde, eğer Rₚ bir ad alanına başvuruyorsa ve Rₚ adlı I olan ve x 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, (büyük olasılıkla oluşturulmuş) bir sınıfa, yapıya veya arabirim türüne başvuruyorsa Rₚ ve Rₚ ya da temel türlerinden herhangi biri ad I ve x 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. Hiçbir tür diğerlerinden daha fazla türetilmemişse bu bir derleyici hatasıdır.

    Not: Bir tür T.I için T'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 formunda T.I veya
  • namespace_or_type_name, T (§12.8.18) şeklindeki ifadede olan typeof(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çin A.NestedClass.M() veya B.NestedClass.M() için açık bir başvuru gereklidir.

son örnek

7.7.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.7.3 Tam 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ı olur N.
  • Aksi takdirde, tam adı S.N şeklindedir; burada S, 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.8 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:

  1. 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.
  2. 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

  3. 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.
  4. 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

  5. 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.1).

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 b değeri nullatandığı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 ve A'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 bir A örneğinin canlı referanstan Test.RefA erişilebilir olmasına neden oldu. Çağrı WaitForPendingFinalizers'den sonra B örneği derleme için uygundur, ancak A referansından dolayı Test.RefA örneği uygun değildir.

son örnek

7.9 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.