Aracılığıyla paylaş


6 Sözcük yapısı

6.1 Programları

C# programı, derleme birimi (§14.2) olarak bilinen bir veya daha fazla kaynak dosyadan oluşur. Derleme biriminin dosya sistemindeki bir dosyayla birebir yazışması olsa da, bu tür bir yazışma gerekli değildir.

Kavramsal olarak bakıldığında, bir program üç adım kullanılarak derlenmiş:

  1. Dönüştürme, bir dosyayı belirli bir karakter repertuarından ve kodlama düzeninden Unicode karakter dizisine dönüştürür.
  2. Unicode giriş karakterleri akışını belirteç akışına çeviren sözcük temelli analiz.
  3. Belirteç akışını yürütülebilir koda çeviren bozulma analizi.

Uyumlu uygulamalar UTF-8 kodlama formuyla kodlanmış Unicode derleme birimlerini kabul edecektir (Unicode standardı tarafından tanımlandığı gibi) ve bunları unicode karakter dizisine dönüştürecektir. Uygulamalar ek karakter kodlama düzenlerini (UTF-16, UTF-32 veya Unicode olmayan karakter eşlemeleri gibi) kabul etmeyi ve dönüştürmeyi seçebilir.

Not: Unicode NULL karakterinin (U+0000) işlenmesi uygulama tanımlıdır. Geliştiricilerin hem taşınabilirlik hem de okunabilirlik açısından kaynak kodlarında bu karakteri kullanmaktan kaçınmaları kesinlikle önerilir. Karakter veya dize değişmez değeri içinde karakter gerekli olduğunda, kaçış dizileri \0 veya \u0000 bunun yerine kullanılabilir. son not

Not: Unicode dışında bir karakter gösterimi kullanan bir dosyanın unicode karakter dizisine nasıl dönüştürülebileceğini tanımlamak bu belirtim kapsamının dışındadır. Ancak bu tür dönüştürme sırasında, diğer karakter kümesindeki normal satır ayırma karakterinin (veya sırasının), Unicode satır başı karakterinden (U+000D) ve ardından Unicode satır besleme karakterinden (U+000A) oluşan iki karakterli diziye çevrilmesi önerilir. Çoğunlukla bu dönüşümün görünür bir etkisi olmayacaktır; ancak, düz metin dize değişmez belirteçlerinin (§6.4.5.6) yorumlanmasını etkiler. Bu önerinin amacı, özellikle de satır ayrımı için farklı karakter dizileri kullanan farklı Unicode olmayan karakter kümelerini destekleyen sistemler arasında derleme birimi taşındığında, düz metin dizesi değişmez değerlerinin aynı karakter dizisini üretmesine izin vermektir. son not

6.2 Dil Bilgisi

6.2.1 Genel

Bu belirtim, iki dil bilgisi kullanarak C# programlama dilinin söz dizimini sunar. Sözcük temelli dil bilgisi (§6.2.3), Unicode karakterlerin satır sonlandırıcıları, boşluk, açıklamalar, belirteçler ve ön işleme yönergelerini oluşturmak için nasıl birleştirildiği tanımlar. İlgili dil bilgisi (§6.2.4), sözcük temelli dil bilgisinden kaynaklanan belirteçlerin C# programları oluşturmak için nasıl birleştirildiği tanımlar.

Tüm terminal karakterleri, diğer Unicode karakter aralıklarından benzer görünen karakterler yerine U+0020 ile U+007F aralığından uygun Unicode karakter olarak anlaşılmalıdır.

6.2.2 Dil bilgisi gösterimi

Sözcük temelli ve yazımsal dil bilgisi, ANTLR dil bilgisi aracının Genişletilmiş Backus-Naur formunda sunulur.

ANTLR gösterimi kullanılırken, bu belirtim C# için ANTLR'ye hazır tam bir "başvuru dil bilgisi" sunmaz; el ile veya ANTLR gibi bir araç kullanarak sözcük oluşturucu ve ayrıştırıcı yazma, dil belirtiminin kapsamı dışındadır. Bu nitelemeyle, bu belirtim belirtilen dil bilgisi ile ANTLR'de bir sözcük oluşturucu ve ayrıştırıcı oluşturmak için gereken arasındaki boşluğu en aza indirmeyi dener.

ANTLR, büyük harfle sözcüksel kurallar ve küçük harfli ayrıştırıcı kuralları başlatarak ANTLR tarafından terimleştirilmiş, antlr tarafından terimleştirilmiş ayrıştırıcı, gösterimindeki dil bilgisi değerlerini birbirinden ayırır.

Not: C# sözcüksel dil bilgisi (§6.2.3) ve bozulmamış dil bilgisi (§6.2.4), ANTLR'nin sözcük temelli ve ayrıştırıcı gramerlere bölünmesiyle tam olarak eşleşmez. Bu küçük uyuşmazlık, C# sözcük bilgisi belirtilirken bazı ANTLR ayrıştırıcı kurallarının kullanıldığı anlamına gelir. son not

6.2.3 Sözcük dil bilgisi

C# sözcüksel dil bilgisi §6.3, §6.4 ve §6.5'te sunulur. Sözcük temelli dil bilgisinin terminal simgeleri Unicode karakter kümesinin karakterleridir ve sözcük temelli dil bilgisi, karakterlerin belirteçler (§6.4), boşluk (§6.3.4), açıklamalar (§6.3.3) ve ön işleme yönergeleri (§6.5) oluşturmak için nasıl birleştirildiği belirtir.

Yazımsal dil bilgisinin terminal simgelerinden çoğu, sözcük temelli dil bilgisi içinde belirteç olarak açıkça tanımlanmaz. Bunun yerine, dilbilgisindeki değişmez dizelerin örtük sözcük temelli belirteçler olarak ayıklanması anTLR davranışından yararlanılır; bu, anahtar sözcüklerin, işleçlerin vb. dil bilgisi içinde belirteç adı yerine değişmez değer gösterimiyle temsil edilmesini sağlar.

Bir C# programındaki her derleme birimi, sözcük temelli dil bilgisinin (§6.3.1) giriş üretimine uygun olmalıdır.

6.2.4 Bozulmamış dil bilgisi

C# öğesinin söz dizimsel dil bilgisi, bu alt uyarıyı izleyen yan tümcelerde, alt tümcelerde ve eklerde sunulur. Söz dizimsel dil bilgisinin terminal simgeleri, sözcük temelli dil bilgisi tarafından açıkça tanımlanan ve dilbilgisinin kendisindeki değişmez dizelerle örtük olarak tanımlanan belirteçlerdir (§6.2.3). İlgili dil bilgisi, belirteçlerin C# programlarını oluşturmak için nasıl birleştirildiği belirtir.

C# programındaki her derleme birimi söz diziminin compilation_unit üretimine (§14.2) uygun olmalıdır.

6.2.5 Dil bilgisi belirsizlikleri

simple_name (§12.8.4) ve member_access (§12.8.7) üretimleri, ifadeler için dil bilgisi belirsizliği doğurabilir.

Örnek: Deyimi:

F(G<A, B>(7));

, ve Folmak üzere iki bağımsız değişkenle G < A çağrısı B > (7) olarak yorumlanabilir. Alternatif olarak, iki tür bağımsız değişken ve bir F normal bağımsız değişken içeren genel bir yönteme G yapılan çağrı olan bir bağımsız değişken ile çağrısı olarak yorumlanabilir.

son örnek

Belirteç dizisi simple_name (§12.8.4), member_access (§12.8.7>

  • ( ) ] } : ; , . ? == != | ^ && || & [bunlardan biri veya
  • İlişkisel işleçlerden < <= >= is asbiri ; veya
  • Sorgu ifadesinin içinde görünen bağlamsal sorgu anahtar sözcüğü; veya
  • Belirli bağlamlarda tanımlayıcı, kesinleştirme belirteci olarak değerlendirilir. Bu bağlamlar, kesinleştirilmiş belirteç dizisinin hemen önce anahtar sözcüklerinden iscase biri veya veya olur ya da outbir tanımlama grubu değişmez değerinin ilk öğesi ayrıştırılırken ortaya çıkar (bu durumda belirteçlerin başına ( veya tanımlayıcısı :gelir) ya da , bir demet değişmez değerinin sonraki bir öğesidir.

Aşağıdaki belirteç bu liste arasındaysa veya bu bağlamda bir tanımlayıcıysa, type_argument_list simple_name, member_access veya pointer_member erişimi kapsamında tutulur ve belirteç dizisinin diğer olası ayrıştırması atılır. Aksi takdirde, belirteç dizisinin başka bir olası ayrıştırması olmasa bile type_argument_list simple_name, member_access veya pointer_member_access parçası olarak kabul edilmez.

Not: Bu kurallar, namespace_or_type_name bir type_argument_listayrıştırılırken uygulanmaz (§7.8). son not

Örnek: Deyimi:

F(G<A, B>(7));

will, bu kurala göre, iki tür bağımsız değişken ve bir F normal bağımsız değişken içeren genel bir yönteme G yapılan çağrı olan bir bağımsız değişkenle çağrısı olarak yorumlanır. Deyimleri

F(G<A, B>7);
F(G<A, B>>7);

her bir çağrı olarak iki bağımsız değişkenle yorumlanır F . Deyimi

x = F<A> + y;

, deyimi yazılmış gibi küçüktür işleci, büyüktür işleci ve bire artı işleci olarak yorumlanır; bunun yerine, type_argument_list ve ardından ikili artı işleci olan bir simple_namex = (F < A) > (+y) olarak yazılır. deyiminde

x = y is C<T> && z;

belirteçlerC<T>, type_argument_list sonra && olarak yorumlanır.

İfade (A < B, C > D) , her biri bir karşılaştırma olmak üzere iki öğe içeren bir tanımlama grubudur.

İfade (A<B,C> D, E) , ilki bildirim ifadesi olan iki öğe içeren bir tanımlama grubudur.

Çağırmanın M(A < B, C > D, E) üç bağımsız değişkeni vardır.

Çağırmanın M(out A<B,C> D, E) iki bağımsız değişkeni vardır ve bunlardan ilki bir out bildirimdir.

İfade e is A<B> C bir bildirim deseni kullanır.

Servis talebi etiketi case A<B> C: bir bildirim deseni kullanır.

son örnek

Bir relational_expression tanınırken (§12.12.1) hem "relational_expression türü" hem de "relational_expression isis constant_pattern" alternatifleri geçerliyse ve tür erişilebilir bir türe çözümleniyorsa, "istürü" alternatifi seçilmelidir.

6.3 Sözcük temelli analiz

6.3.1 Genel

Kolaylık sağlamak için sözcük temelli dil bilgisi aşağıdaki adlandırılmış lexer belirteçlerini tanımlar ve bunlara başvurur:

DEFAULT  : 'default' ;
NULL     : 'null' ;
TRUE     : 'true' ;
FALSE    : 'false' ;
ASTERISK : '*' ;
SLASH    : '/' ;

Bunlar sözcük temelli kurallar olsa da, bu adlar normal sözcük denetleyicisi kural adlarından ayırt etmek için büyük harflerle yazılır.

Not: Bu kolaylık kuralları, değişmez değer dizeleri tarafından tanımlanan belirteçler için açık belirteç adları sağlamama normal uygulamasının özel durumlarıdır. son not

Giriş üretimi, C# derleme biriminin sözcüksel yapısını tanımlar.

input
    : input_section?
    ;

input_section
    : input_section_part+
    ;

input_section_part
    : input_element* New_Line
    | PP_Directive
    ;

input_element
    : Whitespace
    | Comment
    | token
    ;

Not: Yukarıdaki dil bilgisi ANTLR ayrıştırma kuralları tarafından açıklanmıştır; sözcük temelli belirteçleri değil C# derleme biriminin sözcüksel yapısını tanımlar. son not

C# derleme biriminin sözcük temelli yapısını beş temel öğe oluşturur: Satır sonlandırıcıları (§6.3.2), boşluk (§6.3.4), açıklamalar (§6.3.3), belirteçler (§6.4) ve ön işleme yönergeleri (§6.5). Bu temel öğelerden yalnızca belirteçler C# programının söz diziminde (§6.2.4) önemlidir.

C# derleme biriminin sözcük temelli işlemesi, dosyanın söz dizimsel analizin girişi haline gelen bir belirteç dizisine indirgenmesini içerir. Satır sonlandırıcıları, boşluk ve açıklamalar ayrı belirteçlere hizmet edebilir ve ön işleme yönergeleri derleme biriminin bölümlerinin atlanmasına neden olabilir, ancak aksi takdirde bu sözcük öğeleri C# programının söz dizimi yapısını etkilemez.

Birkaç sözcük bilgisi üretimleri bir derleme birimindeki bir karakter dizisiyle eşleştiğinde, sözcük temelli işleme her zaman mümkün olan en uzun sözcük temelli öğeyi oluşturur.

Örnek: Sözcük temelli öğe tek bir belirteçten daha uzun olduğundan karakter dizisi // tek / satırlı açıklamanın başlangıcı olarak işlenir. son örnek

Bazı belirteçler bir sözcük kuralları kümesi tarafından tanımlanır; bir ana kural ve bir veya daha fazla alt kural. İkincisi, kuralın başka bir belirtecin bir kısmını tanımladığı belirtmek için tarafından dil bilgisi fragment içinde işaretlenir. Parça kuralları, sözcük temelli kuralların yukarıdan aşağıya sıralanmasında dikkate alınmaz.

Not: ANTLR'de fragment , burada tanımlanan davranışın aynısını üreten bir anahtar sözcüktür. son not

6.3.2 Çizgi sonlandırıcıları

Satır sonlandırıcıları, C# derleme biriminin karakterlerini satırlara böler.

New_Line
    : New_Line_Character
    | '\u000D\u000A'    // carriage return, line feed 
    ;

Dosya sonu işaretleyicileri ekleyen kaynak kodu düzenleme araçlarıyla uyumluluk sağlamak ve bir derleme biriminin düzgün şekilde sonlandırılan satır dizisi olarak görüntülenmesini sağlamak için, C# programındaki her derleme birimine sırayla aşağıdaki dönüştürmeler uygulanır:

  • Derleme biriminin son karakteri bir Control-Z karakteri (U+001A) ise, bu karakter silinir.
  • Derleme birimi boş değilse ve derleme biriminin son karakteri satır başı (U+000D), satır beslemesi (U+000A), sonraki satır karakteri (U+0085), satır ayırıcısı (U+2028) veya paragraf ayırıcısı (U+2029) değilse, derleme biriminin sonuna satır başı karakteri (U+000D) eklenir.

Not: Ek satır başı, programın sonlandırıcı New_Line olmayan bir PP_Directive (§6.5) ile bitmesini sağlar. son not

6.3.3 Yorumlar

İki açıklama biçimi desteklenir: sınırlandırılmış açıklamalar ve tek satırlı açıklamalar.

Sınırlandırılmış bir açıklama karakterlerle /* başlar ve karakterleriyle */biter. Sınırlandırılmış açıklamalar bir satırın bir bölümünü, tek bir satırı veya birden çok satırı kaplayabilir.

Örnek: Örnek

/* Hello, world program
   This program writes "hello, world" to the console
*/
class Hello
{
    static void Main()
    {
        System.Console.WriteLine("hello, world");
    }
}

sınırlandırılmış bir açıklama içerir.

son örnek

Tek satırlı açıklama karakterlerle // başlar ve satırın sonuna kadar uzanır.

Örnek: Örnek

// Hello, world program
// This program writes "hello, world" to the console
//
class Hello // any name will do for this class
{
    static void Main() // this method must be named "Main"
    {
        System.Console.WriteLine("hello, world");
    }
}

birkaç tek satırlı açıklama gösterir.

son örnek

Comment
    : Single_Line_Comment
    | Delimited_Comment
    ;

fragment Single_Line_Comment
    : '//' Input_Character*
    ;

fragment Input_Character
    // anything but New_Line_Character
    : ~('\u000D' | '\u000A'   | '\u0085' | '\u2028' | '\u2029')
    ;
    
fragment New_Line_Character
    : '\u000D'  // carriage return
    | '\u000A'  // line feed
    | '\u0085'  // next line
    | '\u2028'  // line separator
    | '\u2029'  // paragraph separator
    ;
    
fragment Delimited_Comment
    : '/*' Delimited_Comment_Section* ASTERISK+ '/'
    ;
    
fragment Delimited_Comment_Section
    : SLASH
    | ASTERISK* Not_Slash_Or_Asterisk
    ;

fragment Not_Slash_Or_Asterisk
    : ~('/' | '*')    // Any except SLASH or ASTERISK
    ;

Açıklamalar iç içe yerleştirilmiyor. /* ile */ karakter dizilerinin tek satırlı bir açıklama içinde ve // ile /* karakter dizilerinin de sınırlandırılmış bir açıklama içinde özel bir anlamı yoktur.

Açıklamalar karakter ve dize değişmez değerleri içinde işlenmez.

Not: Bu kurallar dikkatle yorumlanmalıdır. Örneğin, aşağıdaki örnekte, ile Aarasında B bitmeden önce C() başlayan sınırlandırılmış açıklama. Nedeni şudur:

// B */ C();

aslında tek satırlı bir açıklama değildir, çünkü // sınırlandırılmış bir açıklama içinde özel bir anlamı yoktur ve bu satırda */ her zamanki özel anlamı vardır.

Benzer şekilde, öncesinden başlayan sınırlandırılmış açıklama da tarihinden önce DEsona erer. Bunun nedeni "D */ " aslında bir dize değişmez değeri olmamasıdır çünkü ilk çift tırnak karakteri sınırlandırılmış bir açıklama içinde görünür.

Tek satırlı bir açıklama içinde özel bir anlamı olmamasının /* ve */ bunun yararlı bir sonucu, kaynak kod satırları bloğunun her satırın başına yerleştirilerek // açıklama çıkarılabilmesidir. Genel olarak, bloktaki sınırlandırılmış açıklamaları düzgün bir şekilde kapsüllemediğinden ve genel olarak bu sınırlandırılmış açıklamaların yapısını tamamen değiştireediğinden, bu satırların önüne ve /* arkasına koymak */ işe yaramaz.

Örnek kod:

static void Main()
{
    /* A
    // B */ C();
    Console.WriteLine(/* "D */ "E");
}

son not

Single_Line_Comment ve Delimited_Commentbelirli biçimlere sahip olması , belge açıklamaları olarak §D'de açıklandığı gibi kullanılabilir.

6.3.4 Boşluk

Boşluk, Unicode sınıf Z'leri (boşluk karakterini içeren) ve yatay sekme karakteri, dikey sekme karakteri ve form akışı karakteri olan herhangi bir karakter olarak tanımlanır.

Whitespace
    : [\p{Zs}]  // any character with Unicode class Zs
    | '\u0009'  // horizontal tab
    | '\u000B'  // vertical tab
    | '\u000C'  // form feed
    ;

6.4 Belirteçleri

6.4.1 Genel

Çeşitli belirteç türleri vardır: tanımlayıcılar, anahtar sözcükler, değişmez değerler, işleçler ve noktalama işaretleri. Boşluk ve açıklamalar belirteç değildir, ancak belirteçler için ayırıcı görevi görür.

token
    : identifier
    | keyword
    | Integer_Literal
    | Real_Literal
    | Character_Literal
    | String_Literal
    | operator_or_punctuator
    ;

Not: Bu bir ANTLR ayrıştırıcı kuralıdır, sözcük temelli bir belirteç tanımlamaz, belirteç türlerinin koleksiyonudur. son not

6.4.2 Unicode karakter kaçış dizileri

Unicode kaçış dizisi bir Unicode kod noktasını temsil eder. Unicode kaçış dizileri tanımlayıcılar (§6.4.3), karakter değişmez değerleri (§6.4.5.5), normal dize değişmez değerleri (§6.4.5.6) ve ilişkilendirilmiş normal dize ifadeleri (§12.8.3) olarak işlenir. Unicode kaçış dizisi başka bir konumda (örneğin, bir işleç, noktalama işareti veya anahtar sözcük oluşturmak için) işlenmez.

fragment Unicode_Escape_Sequence
    : '\\u' Hex_Digit Hex_Digit Hex_Digit Hex_Digit
    | '\\U' Hex_Digit Hex_Digit Hex_Digit Hex_Digit
            Hex_Digit Hex_Digit Hex_Digit Hex_Digit
    ;

Unicode karakter kaçış dizisi, "\u" veya "\U" karakterlerini izleyen onaltılık sayı tarafından oluşturulan tek Bir Unicode kod noktasını temsil eder. C# karakter ve dize değerlerinde Unicode kod noktalarının 16 bit kodlamasını kullandığından, için U+10000 aralığındaki U+10FFFF bir Unicode kod noktası iki Unicode vekil kod birimi kullanılarak temsil edilir. Yukarıdaki U+FFFF Unicode kod noktalarına karakter değişmez değerlerinde izin verilmez. Yukarıdaki U+10FFFF Unicode kod noktaları geçersiz ve desteklenmiyor.

Birden çok çeviri gerçekleştirilmiyor. Örneğin, dize değişmez değeri "\u005Cu005C" yerine "\u005C"ile "\" eşdeğerdir.

Not: Unicode değeri \u005C "\" karakteridir. son not

Örnek: Örnek

class Class1
{
    static void Test(bool \u0066)
    {
        char c = '\u0066';
        if (\u0066)
        {
            System.Console.WriteLine(c.ToString());
        }
    }
}

, "\u0066" harfinin kaçış dizisi olan çeşitli kullanımlarını fgösterir. Program,

class Class1
{
    static void Test(bool f)
    {
        char c = 'f';
        if (f)
        {
            System.Console.WriteLine(c.ToString());
        }
    }
}

son örnek

6.4.3 Tanımlayıcıları

Bu alt kodda verilen tanımlayıcıların kuralları, alt çizginin ilk karakter olarak izin verilmesi (C programlama dilinde geleneksel olduğu gibi), tanımlayıcılarda Unicode kaçış sıralarına izin verilmesi ve anahtar sözcüklerin tanımlayıcı olarak kullanılmasını sağlamak için ön ek olarak "@" karakterine izin verilmesi dışında Unicode Standart Ek 15 tarafından önerilenlere tam olarak karşılık gelir.

identifier
    : Simple_Identifier
    | contextual_keyword
    ;

Simple_Identifier
    : Available_Identifier
    | Escaped_Identifier
    ;

fragment Available_Identifier
    // excluding keywords or contextual keywords, see note below
    : Basic_Identifier
    ;

fragment Escaped_Identifier
    // Includes keywords and contextual keywords prefixed by '@'.
    // See note below.
    : '@' Basic_Identifier 
    ;

fragment Basic_Identifier
    : Identifier_Start_Character Identifier_Part_Character*
    ;

fragment Identifier_Start_Character
    : Letter_Character
    | Underscore_Character
    ;

fragment Underscore_Character
    : '_'               // underscore
    | '\\u005' [fF]     // Unicode_Escape_Sequence for underscore
    | '\\U0000005' [fF] // Unicode_Escape_Sequence for underscore
    ;

fragment Identifier_Part_Character
    : Letter_Character
    | Decimal_Digit_Character
    | Connecting_Character
    | Combining_Character
    | Formatting_Character
    ;

fragment Letter_Character
    // Category Letter, all subcategories; category Number, subcategory letter.
    : [\p{L}\p{Nl}]
    // Only escapes for categories L & Nl allowed. See note below.
    | Unicode_Escape_Sequence
    ;

fragment Combining_Character
    // Category Mark, subcategories non-spacing and spacing combining.
    : [\p{Mn}\p{Mc}]
    // Only escapes for categories Mn & Mc allowed. See note below.
    | Unicode_Escape_Sequence
    ;

fragment Decimal_Digit_Character
    // Category Number, subcategory decimal digit.
    : [\p{Nd}]
    // Only escapes for category Nd allowed. See note below.
    | Unicode_Escape_Sequence
    ;

fragment Connecting_Character
    // Category Punctuation, subcategory connector.
    : [\p{Pc}]
    // Only escapes for category Pc allowed. See note below.
    | Unicode_Escape_Sequence
    ;

fragment Formatting_Character
    // Category Other, subcategory format.
    : [\p{Cf}]
    // Only escapes for category Cf allowed, see note below.
    | Unicode_Escape_Sequence
    ;

Not:

  • Yukarıda bahsedilen Unicode karakter sınıfları hakkında bilgi için bkz . Unicode Standardı.
  • Parça Available_Identifier , anahtar sözcüklerin ve bağlamsal anahtar sözcüklerin dışlanmasını gerektirir. Bu belirtimdeki dil bilgisi ANTLR ile işlenirse, bu dışlama ANTLR semantiği tarafından otomatik olarak işlenir:
    • Anahtar sözcükler ve bağlamsal anahtar sözcükler, dil bilgisinde değişmez değer dizeleri olarak gerçekleşir.
    • ANTLR, bu değişmez değer dizelerinden örtük sözcük temelli belirteç kuralları oluşturur.
    • ANTLR, bu örtük kuralları dil bilgisindeki açık sözcük kurallarından önce dikkate alır.
    • Bu nedenle parça Available_Identifier , anahtar sözcüklerle veya bağlamsal anahtar sözcüklerle eşleşmez. Bu nedenle, öncekiler için sözcük kuralları kullanılır.
  • Parça Escaped_Identifier , kaçış anahtar sözcükleri ve bağlamsal anahtar sözcükleri içerir. Bu anahtar sözcükler, bir ve sözcük temelli işleme ile başlayan uzun belirtecin parçası @ olarak her zaman mümkün olan en uzun sözcük temelli öğeyi (§6.3.1) oluşturur.
  • Bir uygulamanın izin verilen Unicode_Escape_Sequence değerleri üzerindeki kısıtlamaları nasıl zorunlu kılması bir uygulama sorunudur.

son not

Örnek: Geçerli tanımlayıcılara örnek olarak identifier1, _identifier2ve @ifverilebilir. son örnek

Uyumlu bir programdaki tanımlayıcı, Unicode Standart Ek 15 tarafından tanımlandığı gibi Unicode Normalleştirme Formu C tarafından tanımlanan kurallı biçimde olmalıdır. C Normalleştirme Formu'nda olmayan bir tanımlayıcıyla karşılaşıldığında davranış uygulama tanımlıdır; ancak tanılama gerekli değildir.

"@" ön eki, anahtar sözcüklerin tanımlayıcı olarak kullanılmasını sağlar. Bu, diğer programlama dilleriyle birlikte çalışırken kullanışlıdır. Karakter @ aslında tanımlayıcının bir parçası olmadığından, tanımlayıcı diğer dillerde ön ek olmadan normal bir tanımlayıcı olarak görülebilir. Ön eki olan bir @ tanımlayıcıya ayrıntılı tanımlayıcı adı verilir.

Not: Anahtar sözcük olmayan tanımlayıcılar için ön ekin kullanılmasına @ izin verilir, ancak stil açısından kesinlikle önerilmez. son not

Örnek: Örnek:

class @class
{
    public static void @static(bool @bool)
    {
        if (@bool)
        {
            System.Console.WriteLine("true");
        }
        else
        {
            System.Console.WriteLine("false");
        }
    }
}

class Class1
{
    static void M()
    {
        cl\u0061ss.st\u0061tic(true);
    }
}

"" adlı bir parametre alan "classstatic" adlı statik yöntemle "bool" adlı bir sınıf tanımlar. Anahtar sözcüklerde Unicode kaçışlarına izin verilmediğinden, "cl\u0061ss" belirtecinin bir tanımlayıcı olduğunu ve "@class" ile aynı tanımlayıcı olduğunu unutmayın.

son örnek

Aşağıdaki dönüştürmeler uygulandıktan sonra sırasıyla aynı olan iki tanımlayıcı aynı kabul edilir:

  • "@" ön eki kullanılırsa kaldırılır.
  • Her Unicode_Escape_Sequence karşılık gelen Unicode karakterine dönüştürülür.
  • Tüm Formatting_Characterkaldırılır.

adlı _ bir tanımlayıcının semantiği, göründüğü bağlama bağlıdır:

  • Değişken, sınıf veya yöntem gibi adlandırılmış bir program öğesini gösterebilir veya
  • Bir atmayı anlamına gelebilir (§9.2.9.2).

Ardışık iki alt çizgi karakteri (U+005F) içeren tanımlayıcılar uygulama tarafından kullanılmak üzere ayrılır; ancak böyle bir tanımlayıcı tanımlanırsa tanılama gerekmez.

Not: Örneğin, bir uygulama iki alt çizgiyle başlayan genişletilmiş anahtar sözcükler sağlayabilir. son not

6.4.4 Anahtar Sözcükler

Anahtar sözcük , ayrılmış olan tanımlayıcı benzeri bir karakter dizisidir ve karakterin başına @ geçtiği durumlar dışında tanımlayıcı olarak kullanılamaz.

keyword
    : 'abstract' | 'as'       | 'base'       | 'bool'      | 'break'
    | 'byte'     | 'case'     | 'catch'      | 'char'      | 'checked'
    | 'class'    | 'const'    | 'continue'   | 'decimal'   | DEFAULT
    | 'delegate' | 'do'       | 'double'     | 'else'      | 'enum'
    | 'event'    | 'explicit' | 'extern'     | FALSE       | 'finally'
    | 'fixed'    | 'float'    | 'for'        | 'foreach'   | 'goto'
    | 'if'       | 'implicit' | 'in'         | 'int'       | 'interface'
    | 'internal' | 'is'       | 'lock'       | 'long'      | 'namespace'
    | 'new'      | NULL       | 'object'     | 'operator'  | 'out'
    | 'override' | 'params'   | 'private'    | 'protected' | 'public'
    | 'readonly' | 'ref'      | 'return'     | 'sbyte'     | 'sealed'
    | 'short'    | 'sizeof'   | 'stackalloc' | 'static'    | 'string'
    | 'struct'   | 'switch'   | 'this'       | 'throw'     | TRUE
    | 'try'      | 'typeof'   | 'uint'       | 'ulong'     | 'unchecked'
    | 'unsafe'   | 'ushort'   | 'using'      | 'virtual'   | 'void'
    | 'volatile' | 'while'
    ;

Bağlamsal anahtar sözcük, belirli bağlamlarda özel anlamı olan, ancak ayrılmamış olan tanımlayıcı benzeri bir karakter dizisidir ve hem bu bağlamların dışında hem de karakterin başına @ geldiğinde tanımlayıcı olarak kullanılabilir.

contextual_keyword
    : 'add'    | 'alias'      | 'ascending' | 'async'     | 'await'
    | 'by'     | 'descending' | 'dynamic'   | 'equals'    | 'from'
    | 'get'    | 'global'     | 'group'     | 'into'      | 'join'
    | 'let'    | 'nameof'     | 'on'        | 'orderby'   | 'partial'
    | 'remove' | 'select'     | 'set'       | 'unmanaged' | 'value'
    | 'var'    | 'when'       | 'where'     | 'yield'
    ;

Not: Rules anahtar sözcüğü ve contextual_keyword , yeni belirteç türleri eklemedikleri için ayrıştırıcı kurallarıdır. Tüm anahtar sözcükler ve bağlamsal anahtar sözcükler, dilbilgisinde değişmez değer dizeleri (§6.2.3) olarak gerçekleştiğinden örtük sözcük kurallarıyla tanımlanır. son not

Çoğu durumda bağlamsal anahtar sözcüklerin söz dizimsel konumu, normal tanımlayıcı kullanımıyla karıştırılamayacak şekildedir. Örneğin, bir özellik bildirimi içinde get ve set tanımlayıcılarının özel anlamı vardır (§15.7.3). Bu konumlarda veya dışında hiçbir zaman izin verilmeyen bir tanımlayıcı getset olduğundan, bu kullanım bu sözcüklerin tanımlayıcı olarak kullanılmasıyla çakışmaz.

Bazı durumlarda dil bilgisi, bağlamsal anahtar sözcük kullanımını tanımlayıcılardan ayırt etmek için yeterli değildir. Bu gibi durumlarda ikisi arasında nasıl disambiguate olacağı belirtilir. Örneğin, örtük olarak yazılan yerel değişken bildirimlerindeki bağlamsal anahtar sözcük var (§13.6.2) adlı varbildirilen bir türle çakışabilir. Bu durumda, bildirilen ad tanımlayıcının bağlamsal anahtar sözcük olarak kullanılmasından önceliklidir.

Bu tür bir kesinleştirme örneği, yalnızca bildirilen awaitbir yöntemin içinde anahtar sözcük olarak kabul edilen ancak başka bir yerde tanımlayıcı olarak kullanılabilen bağlamsal anahtar sözcüktür (async).

Anahtar sözcüklerde olduğu gibi bağlamsal anahtar sözcükler de karakterin önüne eklenerek @ normal tanımlayıcılar olarak kullanılabilir.

Not: Bağlamsal anahtar sözcükler olarak kullanıldığında, bu tanımlayıcılar Unicode_Escape_Sequenceiçeremez. son not

6.4.5 Değişmez Değerler

6.4.5.1 Genel

Değişmez değer (§12.8.2), bir değerin kaynak kodu gösterimidir.

literal
    : boolean_literal
    | Integer_Literal
    | Real_Literal
    | Character_Literal
    | String_Literal
    | null_literal
    ;

Not: Değişmez değer , diğer belirteç türlerini gruplandırdığından ve yeni bir belirteç türü eklemediğinden ayrıştırıcı kuralıdır. son not

6.4.5.2 Boole değişmez değerleri

İki Boole değişmez değeri vardır: true ve false.

boolean_literal
    : TRUE
    | FALSE
    ;

Not: boolean_literal , diğer belirteç türlerini gruplandırdığından ve yeni bir belirteç türü eklemediğinden ayrıştırıcı kuralıdır. son not

boolean_literal türüdür.bool

6.4.5.3 Tamsayı değişmez değerleri

Tamsayı değişmez değerleri , , intuintve longtürlerinin ulongdeğerlerini yazmak için kullanılır. Tamsayı değişmez değerlerinin üç olası biçimi vardır: ondalık, onaltılık ve ikili.

Integer_Literal
    : Decimal_Integer_Literal
    | Hexadecimal_Integer_Literal
    | Binary_Integer_Literal
    ;

fragment Decimal_Integer_Literal
    : Decimal_Digit Decorated_Decimal_Digit* Integer_Type_Suffix?
    ;

fragment Decorated_Decimal_Digit
    : '_'* Decimal_Digit
    ;
       
fragment Decimal_Digit
    : '0'..'9'
    ;
    
fragment Integer_Type_Suffix
    : 'U' | 'u' | 'L' | 'l' |
      'UL' | 'Ul' | 'uL' | 'ul' | 'LU' | 'Lu' | 'lU' | 'lu'
    ;
    
fragment Hexadecimal_Integer_Literal
    : ('0x' | '0X') Decorated_Hex_Digit+ Integer_Type_Suffix?
    ;

fragment Decorated_Hex_Digit
    : '_'* Hex_Digit
    ;
       
fragment Hex_Digit
    : '0'..'9' | 'A'..'F' | 'a'..'f'
    ;
   
fragment Binary_Integer_Literal
    : ('0b' | '0B') Decorated_Binary_Digit+ Integer_Type_Suffix?
    ;

fragment Decorated_Binary_Digit
    : '_'* Binary_Digit
    ;
       
fragment Binary_Digit
    : '0' | '1'
    ;

Tamsayı değişmez değeri türü aşağıdaki gibi belirlenir:

  • Değişmez değerde sonek yoksa, değerinin temsil edilebileceği bu türlerden ilki vardır: int, uint, , longulong.
  • Değişmez değer veya Utarafından u soneklenmişse, değerinin temsil edilebileceği bu türlerden ilki vardır: uint, ulong.
  • Değişmez değer veya Ltarafından l soneklenmişse, değerinin temsil edilebileceği bu türlerden ilki vardır: long, ulong.
  • Değişmez değer , , UL, , Ul, uL, ul, LU, Luveya lUile lusoneklenmişse, türündedirulong.

Tamsayı değişmez değeriyle temsil edilen değer türün aralığının ulong dışındaysa, derleme zamanı hatası oluşur.

Not: Stil açısından, türündeki değişmez değerleri Lyazarken "l" yerine "long" kullanılması önerilir, çünkü "" harfini "l1" rakamıyla karıştırmak kolaydır. son not

Mümkün int olan en küçük değere ve long değerlerin tamsayı değişmez değerleri olarak yazılmasına izin vermek için aşağıdaki iki kural vardır:

  • Değeri temsil eden bir 2147483648 (2³¹) ve hiçbir Integer_Type_Suffix bir tek eksi işleci belirtecinin (§12.9.3) hemen ardından belirteç olarak göründüğünde, sonuç (her iki belirtecin de) değeri −2147483648 olan int türünde bir sabittir (−2³¹). Diğer tüm durumlarda, böyle bir Integer_Literal türündedir uint.
  • Değeri (2⁶³) temsil eden ve Integer_Type_Suffix veya Integer_Type_Suffix olmayan Lbirli eksi işleci belirtecinin hemen ardından belirteç olarak göründüğünde (l), sonuç (her iki belirtecin de) değeri olan bir tür long sabitidir (−2⁶³).−9223372036854775808 Diğer tüm durumlarda, böyle bir Integer_Literal türündedir ulong.

Örnek:

123                  // decimal, int
10_543_765Lu         // decimal, ulong
1_2__3___4____5      // decimal, int
_123                 // not a numeric literal; identifier due to leading _
123_                 // invalid; no trailing _allowed

0xFf                 // hex, int
0X1b_a0_44_fEL       // hex, long
0x1ade_3FE1_29AaUL   // hex, ulong
0x_abc               // hex, int
_0x123               // not a numeric literal; identifier due to leading _
0xabc_               // invalid; no trailing _ allowed

0b101                // binary, int
0B1001_1010u         // binary, uint
0b1111_1111_0000UL   // binary, ulong
0B__111              // binary, int
__0B111              // not a numeric literal; identifier due to leading _
0B111__              // invalid; no trailing _ allowed

son örnek

6.4.5.4 Gerçek değişmez değerler

Gerçek değişmez değerler, , floatve doubletürlerinin decimaldeğerlerini yazmak için kullanılır.

Real_Literal
    : Decimal_Digit Decorated_Decimal_Digit* '.'
      Decimal_Digit Decorated_Decimal_Digit* Exponent_Part? Real_Type_Suffix?
    | '.' Decimal_Digit Decorated_Decimal_Digit* Exponent_Part? Real_Type_Suffix?
    | Decimal_Digit Decorated_Decimal_Digit* Exponent_Part Real_Type_Suffix?
    | Decimal_Digit Decorated_Decimal_Digit* Real_Type_Suffix
    ;

fragment Exponent_Part
    : ('e' | 'E') Sign? Decimal_Digit Decorated_Decimal_Digit*
    ;

fragment Sign
    : '+' | '-'
    ;

fragment Real_Type_Suffix
    : 'F' | 'f' | 'D' | 'd' | 'M' | 'm'
    ;

Real_Type_Suffix belirtilmezse, Real_Literal türü olurdouble. Aksi takdirde, Real_Type_Suffix gerçek değişmez değerin türünü aşağıdaki gibi belirler:

  • veya F türünde fgerçek bir değişmez değer sonekifloat.

    Örnek: , , 1f1.5fve 1e10f değişmez değerlerinin 123.456Ftümü türündedirfloat. son örnek

  • veya D türünde dgerçek bir değişmez değer sonekidouble.

    Örnek: , , 1d1.5dve 1e10d değişmez değerlerinin 123.456Dtümü türündedirdouble. son örnek

  • veya M türünde mgerçek bir değişmez değer sonekidecimal.

    Örnek: , , 1m1.5mve 1e10m değişmez değerlerinin 123.456Mtümü türündedirdecimal. son örnek
    Bu değişmez değer, tam değer alınarak bir decimal değere dönüştürülür ve gerekirse bankacı yuvarlama (§8.3.8) kullanılarak en yakın temsil edilebilir değere yuvarlama yapılır. Değer yuvarlanmadığı sürece değişmez değerde görünen tüm ölçekler korunur. Not: Bu nedenle, değişmez değer 2.900m işareti decimal, katsayısı 0ve ölçek 2900ile oluşturmak 3 için ayrıştırılır. son not

Belirtilen değişmez değerin büyüklüğü belirtilen türde temsil edilemeyecek kadar büyükse, derleme zamanı hatası oluşur.

Not: Özellikle, bir Real_Literal hiçbir zaman kayan nokta sonsuzluğu üretmez. Ancak sıfır olmayan bir Real_Literal sıfıra yuvarlanabilir. son not

Türün float veya double gerçek değişmez değerinin değeri, "eşit" olarak (en az önemli bit sıfır olan bir değer) ve tüm basamakların önemli olarak kabul edildiği IEC 60559 "en yakına yuvarla" modu kullanılarak belirlenir.

Not: Gerçek değişmez değerde ondalık basamaklar her zaman ondalık ayırıcıdan sonra gereklidir. Örneğin, 1.3F gerçek bir değişmez değerdir ancak 1.F değildir. son not

Örnek:

1.234_567      // double
.3e5f          // float
2_345E-2_0     // double
15D            // double
19.73M         // decimal
1.F            // parsed as a member access of F due to non-digit after .
1_.2F          // invalid; no trailing _ allowed in integer part
1._234         // parsed as a member access of _234 due to non-digit after .
1.234_         // invalid; no trailing _ allowed in fraction
.3e_5F         // invalid; no leading _ allowed in exponent
.3e5_F         // invalid; no trailing _ allowed in exponent

son örnek

6.4.5.5 Karakter değişmez değerleri

Karakter değişmez değeri tek bir karakteri temsil eder ve içinde olduğu gibi 'a'tırnak içinde bir karakterden oluşur.

Character_Literal
    : '\'' Character '\''
    ;
    
fragment Character
    : Single_Character
    | Simple_Escape_Sequence
    | Hexadecimal_Escape_Sequence
    | Unicode_Escape_Sequence
    ;
    
fragment Single_Character
    // anything but ', \, and New_Line_Character
    : ~['\\\u000D\u000A\u0085\u2028\u2029]
    ;
    
fragment Simple_Escape_Sequence
    : '\\\'' | '\\"' | '\\\\' | '\\0' | '\\a' | '\\b' |
      '\\f' | '\\n' | '\\r' | '\\t' | '\\v'
    ;
    
fragment Hexadecimal_Escape_Sequence
    : '\\x' Hex_Digit Hex_Digit? Hex_Digit? Hex_Digit?
    ;

Not: Karakterde ters eğik çizgi karakterinden (\) sonra gelen bir karakter şu karakterlerden biri olmalıdır: ', ", \, , 0, a, , b, f, n, r, tuUx, . v Aksi takdirde derleme zamanı hatası oluşur. son not

Not: Hexadecimal_Escape_Sequence üretiminin \xkullanımı hataya açık olabilir ve değerini izleyen \xonaltılık basamakların değişken sayısı nedeniyle zor okunabilir. Örneğin, kodda:

string good = "\x9Good text";
string bad = "\x9Bad text";

başta, baştaki karakterin her iki dizede de aynı (U+0009sekme karakteri) olduğu görünebilir. Aslında ikinci dize ile U+9BAD başlar ve "Hatalı" sözcüğündeki üç harfin tümü geçerli onaltılık basamaklardır. Stil açısından, belirli kaçış dizileri (\xbu örnekte) veya sabit uzunlukta \t kaçış dizisinin kullanılmasından kaçınılması önerilir\u.

son not

Onaltılık kaçış dizisi, tek bir Unicode UTF-16 kod birimini temsil eder ve değeri onaltılık sayı tarafından oluşturulan "\x".

Karakter değişmez değeriyle gösterilen değer değerinden U+FFFFbüyükse, derleme zamanı hatası oluşur.

Karakter değişmez değeri içindeki Unicode kaçış dizisi (§6.4.2) ile aralığında U+0000U+FFFFolmalıdır.

Basit çıkış dizisi, aşağıdaki tabloda açıklandığı gibi bir Unicode karakterini temsil eder.

Kaçış dizisi Karakter adı Unicode kod noktası
\' Tek tırnak U+0027
\" Çift tırnak U+0022
\\ Ters eğik çizgi U+005C
\0 Boş U+0000
\a Uyarı U+0007
\b Geri Al tuşu U+0008
\f Form akışı U+000C
\n Yeni satır U+000A
\r Satır başı U+000D
\t Yatay sekme U+0009
\v Dikey sekme U+000B

Character_Literal türü şeklindedirchar.

6.4.5.6 Dize değişmez değerleri

C# iki dize değişmez değerini destekler: normal dize değişmez değerleri ve düz metin dize değişmez değerleri. Normal dize değişmez değeri, içinde "hello"olduğu gibi çift tırnak içine alınmış sıfır veya daha fazla karakterden oluşur ve hem basit kaçış dizilerini (sekme karakteri gibi \t ) hem de onaltılık ve Unicode kaçış dizilerini içerebilir.

Düz metin dizesi değişmez değeri, bir @ karakterin ardından çift tırnak karakteri, sıfır veya daha fazla karakter ve kapanış çift tırnak karakterinden oluşur.

Örnek: Basit bir örnektir @"hello". son örnek

Düz metin dize değişmez değerde, sınırlayıcılar arasındaki karakterler tamsayı olarak yorumlanır ve tek özel durum bir çift tırnak karakterini temsil eden bir Quote_Escape_Sequence olur. Özellikle, basit kaçış dizileri ve onaltılık ve Unicode kaçış dizileri tam dize değişmez değerlerinde işlenmez. Düz metin dizesi değişmez değeri birden çok satıra yayılabilir.

String_Literal
    : Regular_String_Literal
    | Verbatim_String_Literal
    ;
    
fragment Regular_String_Literal
    : '"' Regular_String_Literal_Character* '"'
    ;
    
fragment Regular_String_Literal_Character
    : Single_Regular_String_Literal_Character
    | Simple_Escape_Sequence
    | Hexadecimal_Escape_Sequence
    | Unicode_Escape_Sequence
    ;

fragment Single_Regular_String_Literal_Character
    // anything but ", \, and New_Line_Character
    : ~["\\\u000D\u000A\u0085\u2028\u2029]
    ;

fragment Verbatim_String_Literal
    : '@"' Verbatim_String_Literal_Character* '"'
    ;
    
fragment Verbatim_String_Literal_Character
    : Single_Verbatim_String_Literal_Character
    | Quote_Escape_Sequence
    ;
    
fragment Single_Verbatim_String_Literal_Character
    : ~["]     // anything but quotation mark (U+0022)
    ;
    
fragment Quote_Escape_Sequence
    : '""'
    ;

Örnek: Örnek

string a = "Happy birthday, Joel"; // Happy birthday, Joel
string b = @"Happy birthday, Joel"; // Happy birthday, Joel
string c = "hello \t world"; // hello world
string d = @"hello \t world"; // hello \t world
string e = "Joe said \"Hello\" to me"; // Joe said "Hello" to me
string f = @"Joe said ""Hello"" to me"; // Joe said "Hello" to me
string g = "\\\\server\\share\\file.txt"; // \\server\share\file.txt
string h = @"\\server\share\file.txt"; // \\server\share\file.txt
string i = "one\r\ntwo\r\nthree";
string j = @"one
two
three";

çeşitli dize değişmez değerleri gösterir. Son dize değişmez değeri olan , jbirden çok satıra yayılan bir düz metin dizesi değişmez değeridir. Yeni satır karakterleri gibi boşluklar da dahil olmak üzere tırnak işaretleri arasındaki karakterler tam olarak korunur ve her çift tırnak karakteri çifti böyle bir karakterle değiştirilir.

son örnek

Not: Tam dize değişmez değerleri içindeki tüm satır sonları, sonuçta elde edilen dizenin bir parçasıdır. Satır sonlarını oluşturmak için kullanılan tam karakterler bir uygulamayla ilgiliyse, kaynak koddaki satır sonlarını farklı biçimlere çeviren tüm araçlar (örneğin, "\n" ile "\r\n" arasında) uygulama davranışını değiştirir. Geliştiriciler bu gibi durumlarda dikkatli olmalıdır. son not

Not: Onaltılık bir kaçış dizisinin değişken sayıda onaltılık basamakları olabileceğinden, dize değişmez değeri "\x123" onaltılık değere 123sahip tek bir karakter içerir. Onaltılık değere 12 ve ardından karakterine sahip karakteri 3içeren bir dize oluşturmak için, bir dize yazabilir "\x00123" veya "\x12" + "3" yazabilir. son not

String_Literal türüdür.string

Her dize değişmez değeri mutlaka yeni bir dize örneğine neden olmaz. Dize eşitliği işlecine (§12.12.8) göre eşdeğer olan iki veya daha fazla dize değişmez değeri aynı derlemede göründüğünde, bu dize değişmez değerleri aynı dize örneğine başvurur.

Örnek: Örneğin,

class Test
{
    static void Main()
    {
        object a = "hello";
        object b = "hello";
        System.Console.WriteLine(a == b);
    }
}

bunun nedeni, iki değişmez değerin aynı dize örneğine başvurmasıdır True .

son örnek

6.4.5.7 Null değişmez değer

null_literal
    : NULL
    ;

Not: null_literal , yeni bir belirteç türü tanıtmadığından ayrıştırıcı kuralıdır. son not

null_literal bir null değeri temsil eder. Türü yoktur, ancak null değişmez değer dönüştürmesi (§10.2.7) aracılığıyla herhangi bir başvuru türüne veya null değer türüne dönüştürülebilir.

6.4.6 İşleçler ve noktalama işaretleri

Çeşitli işleçler ve noktalama işaretleri vardır. İşleçler, bir veya daha fazla işlenen içeren işlemleri açıklamak için ifadelerde kullanılır.

Örnek: İfadea + b, ve adlı iki işleneni +aeklemek için işlecini kullanırb. son örnek

Noktalama işaretleri gruplandırma ve ayırmaya yöneliktir.

operator_or_punctuator
    : '{'  | '}'  | '['  | ']'  | '('   | ')'  | '.'  | ','  | ':'  | ';'
    | '+'  | '-'  | ASTERISK    | SLASH | '%'  | '&'  | '|'  | '^'  | '!' | '~'
    | '='  | '<'  | '>'  | '?'  | '??'  | '::' | '++' | '--' | '&&' | '||'
    | '->' | '==' | '!=' | '<=' | '>='  | '+=' | '-=' | '*=' | '/=' | '%='
    | '&=' | '|=' | '^=' | '<<' | '<<=' | '=>'
    ;

right_shift
    : '>'  '>'
    ;

right_shift_assignment
    : '>' '>='
    ;

Not: right_shift ve right_shift_assignment ayrıştırıcı kurallarıdır, yeni bir belirteç türü sunmaz ancak iki belirteç sırasını temsil eder. operator_or_punctuator kuralı yalnızca açıklayıcı amaçlarla mevcuttur ve dil bilgisinin başka bir yerinde kullanılmaz. son not

right_shift iki belirteçten > oluşur ve >. Benzer şekilde, right_shift_assignment ve iki belirteçten >>=oluşur. Söz dizimindeki diğer üretimlerden farklı olarak, bu üretimlerin her birinde iki belirteç arasında herhangi bir türde karaktere (boşluk bile yoktur) izin verilmez. Bu üretimler, type_parameter_lists (§15.2.3) doğru şekilde işlenmesini sağlamak için özel olarak ele alınır.

Not: C# >> öğesine genel değerler eklenmeden önce ve >>= her ikisi de tek belirteçti. Ancak, genel türlerin söz dizimi, tür parametrelerini ve tür bağımsız değişkenlerini sınırlandırmak için ve < karakterlerini kullanır>. genellikle gibi List<Dictionary<string, int>>iç içe yerleştirilmiş türlerin kullanılması tercih edilir. Programcının ve > öğesini bir boşlukla ayırmasını > gerektirmek yerine, iki operator_or_punctuatortanımı değiştirildi. son not

6.5 Ön işleme yönergeleri

6.5.1 Genel

Ön işleme yönergeleri, derleme birimlerinin bölümlerini koşullu olarak atlama, hata ve uyarı koşullarını raporlama, kaynak kodun farklı bölgelerini ayırma ve null atanabilir bağlamı ayarlama olanağı sağlar.

Not: "Ön işleme yönergeleri" terimi yalnızca C ve C++ programlama dilleri ile tutarlılık için kullanılır. C# dilinde ayrı bir ön işleme adımı yoktur; ön işleme yönergeleri, sözcük temelli analiz aşamasının bir parçası olarak işlenir. son not

PP_Directive
    : PP_Start PP_Kind PP_New_Line
    ;

fragment PP_Kind
    : PP_Declaration
    | PP_Conditional
    | PP_Line
    | PP_Diagnostic
    | PP_Region
    | PP_Pragma
    | PP_Nullable
    ;

// Only recognised at the beginning of a line
fragment PP_Start
    // See note below.
    : { getCharPositionInLine() == 0 }? PP_Whitespace? '#' PP_Whitespace?
    ;

fragment PP_Whitespace
    : ( [\p{Zs}]  // any character with Unicode class Zs
      | '\u0009'  // horizontal tab
      | '\u000B'  // vertical tab
      | '\u000C'  // form feed
      )+
    ;

fragment PP_New_Line
    : PP_Whitespace? Single_Line_Comment? New_Line
    ;

Not:

  • ön işlemci dil bilgisi, tüm ön işleme yönergeleri için kullanılan tek bir sözcük temelli belirteci PP_Directive tanımlar. Ön işleme yönergelerinin her birinin semantiği bu dil belirtiminde tanımlanır, ancak bunların nasıl uygulandığını tanımlamaz.
  • Parçanın PP_Start yalnızca bir satırın başında tanınması gerekir. getCharPositionInLine() == 0 Yukarıdaki ANTLR sözcük temelli koşulu, bunun elde edilebileceği tek bir yolu önerir ve yalnızca bilgilendiricidir, bir uygulama farklı bir strateji kullanabilir.

son not

Aşağıdaki ön işleme yönergeleri kullanılabilir:

  • #define ve #undef, koşullu derleme sembollerini (§6.5.4) tanımlamak ve tanımlamak için kullanılır.
  • #if, #elif, #elseve #endif, kaynak kodun koşullu bölümlerini atlamak için kullanılır (§6.5.5).
  • #line, hata ve uyarılarda (§6.5.8) yayılan satır numaralarını denetlemek için kullanılır.
  • #error, hata vermek için kullanılır (§6.5.6).
  • #region ve #endregion, kaynak kodun (§6.5.7) bölümlerini açıkça işaretlemek için kullanılır.
  • #nullable, null atanabilir bağlamı (§6.5.9) belirtmek için kullanılır.
  • #pragma, derleyiciye isteğe bağlı bağlamsal bilgileri belirtmek için kullanılır (§6.5.10).

Ön işleme yönergesi her zaman ayrı bir kaynak kodu satırını kaplar ve her zaman bir # karakter ve bir ön işleme yönerge adı ile başlar. Karakterden önce # ve karakter ile yönerge adı arasında # boşluk oluşabilir.

, , , , #define, , #undef, #if#elif, #else#endif, veya #line yönergesi içeren bir #endregionkaynak satırı tek satırlı bir açıklamayla bitebilir. #nullable Ön işleme yönergelerini içeren kaynak satırlarda sınırlandırılmış açıklamalara ( /* */ açıklama stili) izin verilmez.

Ön işleme yönergeleri, C# dilinin sözdizimi dil bilgisinin bir parçası değildir. Ancak, ön işleme yönergeleri belirteç dizilerini dahil etmek veya dışlamak için kullanılabilir ve bu şekilde bir C# programının anlamını etkileyebilir.

Örnek: Derlendiğinde, program

#define A
#undef B
class C
{
#if A
    void F() {}
#else
    void G() {}
#endif
#if B
    void H() {}
#else    
    void I() {}
#endif
}

programla tam olarak aynı belirteç dizisiyle sonuçlanmıştır

class C
{
    void F() {}
    void I() {}
}

Bu nedenle, sözcüksel olarak, iki program oldukça farklıdır, bozulmadan, aynıdır.

son örnek

6.5.2 Koşullu derleme simgeleri

, , #if#elifve #else yönergeleri tarafından #endifsağlanan koşullu derleme işlevselliği, ön işleme ifadeleri (§6.5.3) ve koşullu derleme simgeleri aracılığıyla denetlenmektedir.

fragment PP_Conditional_Symbol
    // Must not be equal to tokens TRUE or FALSE. See note below.
    : Basic_Identifier
    ;

Not Bir uygulamanın izin verilen Basic_Identifier değerleri üzerindeki kısıtlamayı nasıl zorunlu kılması bir uygulama sorunudur. son not

Aşağıdaki dönüştürmeler uygulandıktan sonra sırasıyla aynı olan iki koşullu derleme simgesi aynı kabul edilir:

  • Her Unicode_Escape_Sequence karşılık gelen Unicode karakterine dönüştürülür.
  • Tüm Formatting_Characters kaldırılır.

Koşullu derleme simgesinin iki olası durumu vardır: tanımlı veya tanımsız. Derleme biriminin sözcük temelli işlenmesinin başında, bir dış mekanizma (komut satırı derleyici seçeneği gibi) tarafından açıkça tanımlanmadığı sürece koşullu derleme simgesi tanımlanmamıştır. Bir #define yönerge işlendiğinde, bu yönergede adlı koşullu derleme simgesi bu derleme biriminde tanımlanır. Sembol, aynı simge için bir #undef yönerge işlenene kadar veya derleme biriminin sonuna ulaşılana kadar tanımlı kalır. Bunun bir etkisi, bir derleme birimindeki ve #define yönergelerinin aynı programdaki diğer derleme birimleri üzerinde hiçbir etkisi olmamasıdır#undef.

Ön işleme ifadesinde (§6.5.3) başvurulduğunda, tanımlı bir koşullu derleme simgesi Boole değerine trueve tanımsız bir koşullu derleme simgesi boole değerine falsesahiptir. Koşullu derleme simgelerinin ön işleme ifadelerinde başvurulmadan önce açıkça bildirilmesi gerekmez. Bunun yerine, bildirilmemiş simgeler yalnızca tanımlanmamıştır ve bu nedenle değerine falsesahiptir.

Koşullu derleme simgelerinin ad alanı, C# programındaki diğer tüm adlandırılmış varlıklardan farklıdır. Koşullu derleme simgelerine yalnızca ve #define yönergelerinde #undef ve ön işleme ifadelerinde başvurulabilir.

6.5.3 Ön işleme ifadeleri

ön işleme ifadeleri ve #if yönergelerinde #elif oluşabilir. İşleçler ! (yalnızca ön ek mantıksal olumsuzlama), ==, !=, &&ve || ön işleme ifadelerinde izin verilir ve gruplandırma için parantezler kullanılabilir.

fragment PP_Expression
    : PP_Whitespace? PP_Or_Expression PP_Whitespace?
    ;
    
fragment PP_Or_Expression
    : PP_And_Expression (PP_Whitespace? '||' PP_Whitespace? PP_And_Expression)*
    ;
    
fragment PP_And_Expression
    : PP_Equality_Expression (PP_Whitespace? '&&' PP_Whitespace?
      PP_Equality_Expression)*
    ;

fragment PP_Equality_Expression
    : PP_Unary_Expression (PP_Whitespace? ('==' | '!=') PP_Whitespace?
      PP_Unary_Expression)*
    ;
    
fragment PP_Unary_Expression
    : PP_Primary_Expression
    | '!' PP_Whitespace? PP_Unary_Expression
    ;
    
fragment PP_Primary_Expression
    : TRUE
    | FALSE
    | PP_Conditional_Symbol
    | '(' PP_Whitespace? PP_Expression PP_Whitespace? ')'
    ;

Bir ön işleme ifadesinde başvurulduğunda, tanımlı bir koşullu derleme simgesi Boole değerine trueve tanımsız bir koşullu derleme simgesi boole değerine falsesahiptir.

Ön işleme ifadesinin değerlendirilmesi her zaman bir Boole değeri verir. Ön işleme ifadesi için değerlendirme kuralları, bir sabit ifadenin (§12.23) kurallarıyla aynıdır, ancak başvurulabilen tek kullanıcı tanımlı varlıklar koşullu derleme simgeleridir.

6.5.4 Tanım yönergeleri

Tanım yönergeleri, koşullu derleme simgelerini tanımlamak veya tanımlamak için kullanılır.

fragment PP_Declaration
    : 'define' PP_Whitespace PP_Conditional_Symbol
    | 'undef' PP_Whitespace PP_Conditional_Symbol
    ;

Yönergenin #define işlenmesi, yönergeyi izleyen kaynak satırdan başlayarak verilen koşullu derleme simgesinin tanımlanmasına neden olur. Benzer şekilde, yönergenin #undef işlenmesi, yönergeyi izleyen kaynak satırdan başlayarak verilen koşullu derleme simgesinin tanımsız hale gelmesine neden olur.

Derleme birimindeki ve #define#undef yönergeleri, derleme ünitesindeki ilk belirteç (§6.4) öncesinde gerçekleşir; aksi takdirde derleme zamanı hatası oluşur. Sezgisel anlamda ve #define yönergeleri derleme #undef ünitesindeki tüm "gerçek kodlardan" önce gelir.

Örnek: Örnek:

#define Enterprise
#if Professional || Enterprise
#define Advanced
#endif
namespace Megacorp.Data
{
#if Advanced
    class PivotTable {...}
#endif
}

geçerli çünkü #define yönergeler derleme birimindeki ilk belirtecin ( namespace anahtar sözcük) önüne geçer.

son örnek

Örnek: Aşağıdaki örnek, bir #define gerçek kodu izlediğinden derleme zamanı hatasıyla sonuçlanır:

#define A
namespace N
{
#define B
#if B
    class Class1 {}
#endif
}

son örnek

, #define bu simgeye herhangi bir araya #undef gelmeden önceden tanımlanmış bir koşullu derleme simgesi tanımlayabilir.

Örnek: Aşağıdaki örnek, A koşullu derleme simgesini tanımlar ve sonra yeniden tanımlar.

#define A
#define A

Koşullu derleme simgelerinin derleme seçenekleri olarak tanımlanmasına izin veren derleyiciler için, bu tür bir yeniden tanımlamanın gerçekleşmesinin alternatif bir yolu, simgeyi hem derleyici seçeneği olarak hem de kaynakta tanımlamaktır.

son örnek

, #undef tanımlanmamış bir koşullu derleme simgesini "tanımsız" yapabilir.

Örnek: Aşağıdaki örnek bir koşullu derleme simgesi A tanımlar ve ardından iki kez tanımlarını kaldırmıştır; ikincisinin #undef etkisi olmasa da, yine de geçerlidir.

#define A
#undef A
#undef A

son örnek

6.5.5 Koşullu derleme yönergeleri

Koşullu derleme yönergeleri, bir derleme biriminin bölümlerini koşullu olarak dahil etmek veya hariç tutmak için kullanılır.

fragment PP_Conditional
    : PP_If_Section
    | PP_Elif_Section
    | PP_Else_Section
    | PP_Endif
    ;

fragment PP_If_Section
    : 'if' PP_Whitespace PP_Expression
    ;
    
fragment PP_Elif_Section
    : 'elif' PP_Whitespace PP_Expression
    ;
    
fragment PP_Else_Section
    : 'else'
    ;
    
fragment PP_Endif
    : 'endif'
    ;

Koşullu derleme yönergeleri, sırasıyla bir #if yönerge, sıfır veya daha fazla #elif yönerge, sıfır veya bir #else yönerge ve bir #endif yönergeden oluşan gruplar halinde yazılmalıdır. Yönergeleri arasında kaynak kodun koşullu bölümleri yer alır. Her bölüm, hemen önceki yönerge tarafından denetlenmektedir. Koşullu bölüm, bu yönergelerin eksiksiz gruplar oluşturması koşuluyla iç içe geçmiş koşullu derleme yönergeleri içerebilir.

Normal sözcük temelli işleme için kapsanan koşullu bölümlerden en az biri seçilir:

  • #elifbiri verene truekadar sırayla değerlendirilir. bir ifadenin verimini verirse true, ilgili yönergeyi izleyen koşullu bölüm seçilir.
  • Tüm #elsekoşullu bölüm seçilir.
  • Aksi takdirde, koşullu bölüm seçilmez.

Varsa, seçilen koşullu bölüm normal bir input_section olarak işlenir: bölümde yer alan kaynak kodu sözcüksel dil bilgisine uymalıdır; bölümdeki kaynak kodundan belirteçler oluşturulur ve bölümdeki ön işleme yönergelerinin önceden belirlenmiş etkileri vardır.

Kalan tüm koşullu bölümler atlanır ve ön işleme yönergeleri dışındaki belirteçler kaynak koddan oluşturulmaz. Bu nedenle ön işleme yönergeleri dışında atlanan kaynak kodu sözcüksel olarak yanlış olabilir. Atlanan ön işleme yönergeleri sözcüksel olarak doğru olmalıdır, ancak başka türlü işlenmez. Atlanan bir koşullu bölüm içinde, iç içe geçmiş tüm koşullu bölümler (iç içe #if...#endif geçmiş yapılarda bulunur) da atlanır.

Not: Yukarıdaki dil bilgisi, ön işleme yönergeleri arasındaki koşullu bölümlerin sözcüksel olarak yanlış biçimlendirilmiş olabileceği iznini yakalamaz. Bu nedenle dil bilgisi ANTLR'ye hazır değildir, yalnızca sözcüksel olarak doğru girişi destekler. son not

Örnek: Aşağıdaki örnekte koşullu derleme yönergelerinin iç içe nasıl yerleştirilebileceği gösterilmektedir:

#define Debug // Debugging on
#undef Trace // Tracing off
class PurchaseTransaction
{
    void Commit()
    {
#if Debug
        CheckConsistency();
    #if Trace
        WriteToLog(this.ToString());
    #endif
#endif
        CommitHelper();
    }
    ...
}

Ön işleme yönergeleri dışında, atlanan kaynak kodu sözcük temelli analize tabi değildir. Örneğin, bölümdeki sonlandırılmamış açıklamaya rağmen aşağıdakiler #else geçerlidir:

#define Debug // Debugging on
class PurchaseTransaction
{
    void Commit()
    {
#if Debug
        CheckConsistency();
#else
        /* Do something else
#endif
    }
    ...
}

Ancak, ön işleme yönergelerinin kaynak kodun atlanan bölümlerinde bile sözcüksel olarak doğru olması gerektiğini unutmayın.

Ön işleme yönergeleri, çok satırlı giriş öğeleri içinde göründüklerinde işlenmez. Örneğin, program:

class Hello
{
    static void Main()
    {
        System.Console.WriteLine(@"hello,
#if Debug
        world
#else
        Nebraska
#endif
        ");
    }
}

sonuç olarak şu çıktıyı elde edin:

hello,
#if Debug
        world
#else
        Nebraska
#endif

Tuhaf durumlarda, işlenen ön işleme yönergeleri kümesi pp_expression değerlendirmesine bağlı olabilir. Örnek:

#if X
    /*
#else
    /* */ class Q { }
#endif

tanımlanıp tanımlanmadığına bakılmaksızın her zaman aynı belirteç akışını (classQ{} ) üretir.X TanımlanırsaX, çok satırlı açıklama nedeniyle yalnızca ve #ifişlenen yönergelerdir#endif. Tanımlanmamışsa X , yönerge kümesinin üç yönergesi (#if, #else, #endif) bir parçasıdır.

son örnek

6.5.6 Tanılama yönergeleri

Tanılama yönergeleri, diğer derleme zamanı hataları ve uyarılarıyla aynı şekilde bildirilen açıkça hata ve uyarı iletileri oluşturmak için kullanılır.

fragment PP_Diagnostic
    : 'error' PP_Message?
    | 'warning' PP_Message?
    ;

fragment PP_Message
    : PP_Whitespace Input_Character*
    ;

Örnek: Örnek

#if Debug && Retail
    #error A build can't be both debug and retail
#endif
class Test {...}

, koşullu derleme simgeleri DebugRetail ve her ikisi de tanımlanmışsa derleme zamanı hatası ("Derleme hem hata ayıklama hem de perakende olamaz") oluşturur. bir PP_Message rastgele metin içerebileceğini, özellikle de sözcüğündeki can'ttek tırnakta gösterildiği gibi iyi biçimlendirilmiş belirteçler içermemesi gerektiğini unutmayın.

son örnek

6.5.7 Bölge yönergeleri

Bölge yönergeleri, kaynak kodun bölgelerini açıkça işaretlemek için kullanılır.

fragment PP_Region
    : PP_Start_Region
    | PP_End_Region
    ;

fragment PP_Start_Region
    : 'region' PP_Message?
    ;

fragment PP_End_Region
    : 'endregion' PP_Message?
    ;

Bir bölgeye semantik anlam eklenmez; bölgeleri, programcı veya kaynak kodun bir bölümünü işaretlemek için otomatik araçlar tarafından kullanılmak üzere tasarlanmıştır. Her #endregion yönergeye uyan bir #region yönerge olacaktır. Aynı şekilde bir #region veya #endregion yönergesinde belirtilen iletinin anlamsal bir anlamı yoktur; yalnızca bölgeyi tanımlamaya hizmet eder. Eşleştirme #region ve #endregion yönergelerin farklı PP_Messageolabilir.

Bir bölgenin sözcük temelli işlenmesi:

#region
...
#endregion

formun koşullu derleme yönergesinin sözcük temelli işlenmesine tam olarak karşılık gelir:

#if true
...
#endif

Not: Bu, bir bölgenin bir veya daha fazla #if/.../#endif içerebileceği veya bir /.../#if içindeki #endifkoşullu bölümle kapsanabileceği anlamına gelir; ancak bir bölge /.../#if öğesinin #endifyalnızca bir bölümüyle çakışamaz veya farklı koşullu bölümlerde başlatılamaz ve sonlandırılamaz. son not

6.5.8 Satır yönergeleri

Satır yönergeleri, çıkışta bir derleyici tarafından bildirilen satır numaralarını ve derleme birimi adlarını (uyarılar ve hatalar gibi) değiştirmek için kullanılabilir. Bu değerler, çağıran-bilgi öznitelikleri (§22.5.6) tarafından da kullanılır.

Not: Satır yönergeleri en yaygın olarak başka bir metin girişinden C# kaynak kodu oluşturan meta programlama araçlarında kullanılır. son not

fragment PP_Line
    : 'line' PP_Whitespace PP_Line_Indicator
    ;

fragment PP_Line_Indicator
    : Decimal_Digit+ PP_Whitespace PP_Compilation_Unit_Name
    | Decimal_Digit+
    | DEFAULT
    | 'hidden'
    ;
    
fragment PP_Compilation_Unit_Name
    : '"' PP_Compilation_Unit_Name_Character* '"'
    ;
    
fragment PP_Compilation_Unit_Name_Character
    // Any Input_Character except "
    : ~('\u000D' | '\u000A'   | '\u0085' | '\u2028' | '\u2029' | '"')
    ;

hiçbir #line yönergesi olmadığında, derleyici çıktısında gerçek satır numaralarını ve derleme birimi adlarını bildirir. olmayan bir PP_Line_Indicator içeren bir yönergesi işlenirken, derleyici yönergeyi sonra satır verilen satır numarasına (ve belirtilmişse derleme birimi adına) sahip olarak ele alır.

için Decimal_Digit+ izin verilen en yüksek değer uygulama tanımlıdır.

Yönerge #line default , önceki #line tüm yönergelerin etkisini geri alır. Derleyici, sonraki satırlar için doğru satır bilgilerini, sanki hiçbir #line yönergesi işlenmemiş gibi, tam olarak bildirir.

Yönergenin#line hidden, hata iletilerinde bildirilen veya (CallerLineNumberAttribute) ile üretilen derleme birimi ve satır numaraları üzerinde hiçbir etkisi yoktur. Kaynak düzeyinde hata ayıklama araçlarını etkilemek için tasarlanmıştır; böylece hata ayıklarken, bir #line hidden yönerge ile sonraki #line yönerge (yani) #line hiddenarasındaki tüm satırlarda satır numarası bilgisi yoktur ve kodda ilerlerken tamamen atlanır.

Not: bir PP_Compilation_Unit_Name kaçış dizisi gibi görünen bir metin içerse de, bu tür metin bir kaçış dizisi değildir; bu bağlamda '\' karakteri yalnızca sıradan bir ters eğik çizgi karakteri belirtir. son not

6.5.9 Null atanabilir yönergesi

Null atanabilir yönergesi, aşağıda açıklandığı gibi null atanabilir bağlamı denetler.

fragment PP_Nullable
    : 'nullable' PP_Whitespace PP_Nullable_Action
      (PP_Whitespace PP_Nullable_Target)?
    ;
fragment PP_Nullable_Action
    : 'disable'
    | 'enable'
    | 'restore'
    ;
fragment PP_Nullable_Target
    : 'warnings'
    | 'annotations'
    ;

Null atanabilir yönerge, başka bir null atanabilir yönerge geçersiz kılana kadar veya derleme _unit sonuna ulaşılana kadar sonraki kod satırları için kullanılabilir bayrakları ayarlar. Null atanabilir bağlam iki bayrak içerir: ek açıklamalar ve uyarılar. Null atanabilir yönergenin her biçiminin etkisi aşağıdaki gibidir:

  • #nullable disable: Hem null atanabilir ek açıklamaları hem de null atanabilir uyarı bayraklarını devre dışı bırakır.
  • #nullable enable: Hem null atanabilir ek açıklamaları hem de null atanabilir uyarı bayraklarını etkinleştirir.
  • #nullable restore: Varsa, hem ek açıklamaları hem de uyarı bayraklarını dış mekanizma tarafından belirtilen duruma geri yükler.
  • #nullable disable annotations: Null atanabilir ek açıklamalar bayrağını devre dışı bırakır. Null atanabilir uyarılar bayrağı etkilenmez.
  • #nullable enable annotations: Null atanabilir ek açıklamalar bayrağını etkinleştirir. Null atanabilir uyarılar bayrağı etkilenmez.
  • #nullable restore annotations: Boş değer atanabilir ek açıklamalar bayrağını varsa dış mekanizma tarafından belirtilen duruma geri yükler. Null atanabilir uyarılar bayrağı etkilenmez.
  • #nullable disable warnings: Null atanabilir uyarılar bayrağını devre dışı bırakır. Null atanabilir ek açıklamalar bayrağı etkilenmez.
  • #nullable enable warnings: Null atanabilir uyarılar bayrağını etkinleştirir. Null atanabilir ek açıklamalar bayrağı etkilenmez.
  • #nullable restore warnings: Varsa, null atanabilir uyarılar bayrağını dış mekanizma tarafından belirtilen duruma geri yükler. Null atanabilir ek açıklamalar bayrağı etkilenmez.

İfadelerin null atanabilir durumu her zaman izlenir. Ek açıklama bayrağının durumu ve null atanabilir bir ek açıklamanın varlığı veya yokluğu, ?değişken bildiriminin ilk null durumunu belirler. Uyarılar yalnızca uyarı bayrağı etkinleştirildiğinde verilir.

Örnek: Örnek

#nullable disable
string x = null;
string y = "";
#nullable enable
Console.WriteLine(x.Length); // Warning
Console.WriteLine(y.Length);

bir derleme zamanı uyarısı ("olduğu xgibinull") üretir. null atanabilir durumu x her yerde izlenir. Uyarılar bayrağı etkinleştirildiğinde bir uyarı verilir.

son örnek

6.5.10 Pragma yönergeleri

Ön #pragma işleme yönergesi, derleyiciye bağlamsal bilgileri belirtmek için kullanılır.

Not: Örneğin, bir derleyici şu yönergeleri sağlayabilir #pragma :

  • Sonraki kodu derlerken belirli uyarı iletilerini etkinleştirin veya devre dışı bırakın.
  • Sonraki koda uygulanacak iyileştirmeleri belirtin.
  • Hata ayıklayıcı tarafından kullanılacak bilgileri belirtin.

son not

fragment PP_Pragma
    : 'pragma' PP_Pragma_Text?
    ;

fragment PP_Pragma_Text
    : PP_Whitespace Input_Character*
    ;

PP_Pragma_Text içindeki Input_Character, derleyici tarafından uygulamaya göre belirlenmiş bir biçimde yorumlanır. Yönergede #pragma verilen bilgiler program semantiğini değiştirmez. Yönerge #pragma yalnızca bu dil belirtiminin kapsamı dışında olan derleyici davranışını değiştirecektir. Derleyici Input_Characteryorumlayamıyorsa, derleyici bir uyarı üretebilir; ancak derleme zamanı hatası oluşturmaz.

Not: PP_Pragma_Text rastgele metin içerebilir; özellikle iyi biçimlendirilmiş belirteçler içermesi gerekmez. son not