C# ön işlemci yönergeleri

Derleyicinin ayrı bir ön işlemcisi olmasa da, bu bölümde açıklanan yönergeler bir tane varmış gibi işlenir. Bunları koşullu derlemede yardımcı olması için kullanırsınız. C ve C++ yönergelerinin aksine, makro oluşturmak için bu yönergeleri kullanamazsınız. Önişlemci yönergesi, bir satırdaki tek yönerge olmalıdır.

Boş değer atanabilir bağlam

#nullable Önişlemci yönergesi, null atanabilir ek açıklama bağlamını ve null atanabilir uyarı bağlamını ayarlar. Bu yönerge, null atanabilir ek açıklamaların etkili olup olmadığını ve null atanabilirlik uyarılarının verilip verilmeyeceğini denetler. Her bağlam devre dışı veyaetkindir.

Her iki bağlam da proje düzeyinde (C# kaynak kodunun dışında) belirtilebilir. yönergesi #nullable ek açıklama ve uyarı bağlamlarını denetler ve proje düzeyi ayarlarından önceliklidir. Yönerge, başka bir yönerge onu geçersiz kılana kadar veya kaynak dosyanın sonuna kadar denetleyeceğini bağlamları ayarlar.

Yönergelerin etkisi aşağıdaki gibidir:

  • #nullable disable: Null atanabilir ek açıklamayı ve uyarı bağlamlarını devre dışı olarak ayarlar.
  • #nullable enable: Null atanabilir ek açıklamayı ve uyarı bağlamlarını etkin olarak ayarlar.
  • #nullable restore: Null değer atanabilir ek açıklamayı ve uyarı bağlamlarını proje ayarlarına geri yükler.
  • #nullable disable annotations: Null atanabilir ek açıklama bağlamını devre dışı olarak ayarlar.
  • #nullable enable annotations: Null atanabilir ek açıklama bağlamını etkin olarak ayarlar.
  • #nullable restore annotations: Null değer atanabilir ek açıklama bağlamını proje ayarlarına geri yükler.
  • #nullable disable warnings: Null atanabilir uyarı bağlamını devre dışı olarak ayarlar.
  • #nullable enable warnings: Null atanabilir uyarı bağlamını etkin olarak ayarlar.
  • #nullable restore warnings: Null atanabilir uyarı bağlamını proje ayarlarına geri yükler.

Koşullu derleme

Koşullu derlemeyi denetlemek için dört önişlemci yönergesi kullanırsınız:

  • #if: Kodun yalnızca belirtilen simge tanımlandığında derlendiği koşullu derlemeyi açar.
  • #elif: Önceki koşullu derlemeyi kapatır ve belirtilen simgenin tanımlanıp tanımlanmadığını temel alan yeni bir koşullu derleme açar.
  • #else: Önceki koşullu derlemeyi kapatır ve belirtilen önceki simge tanımlanmamışsa yeni bir koşullu derleme açar.
  • #endif: Önceki koşullu derlemeyi kapatır.

C# derleyicisi, yönergesi ile #endif yönergesi #if arasındaki kodu yalnızca belirtilen simge tanımlandığında veya not işleci kullanıldığında tanımlanmadığında ! derler. C ve C++'ın aksine, bir simgeye sayısal değer atanamaz. #if C# dilindeki deyimi Boole değeridir ve yalnızca sembolün tanımlanıp tanımlanmadığını sınar. Örneğin, aşağıdaki kod tanımlandığında DEBUG derlenmiş:

#if DEBUG
    Console.WriteLine("Debug version");
#endif

TanımlanmadığındaMYTEST aşağıdaki kod derlenmiş:

#if !MYTEST
    Console.WriteLine("MYTEST is not defined");
#endif

veya falsedeğerlerini test etmek için bool işleçleri true== (eşitlik) ve != (eşitsizlik) kullanabilirsiniz. true simgenin tanımlandığı anlamına gelir. deyimi #if DEBUG ile aynı anlama #if (DEBUG == true)sahiptir. Birden çok simge tanımlanıp tanımlanmadığını &&değerlendirmek için (ve), || (veya) ve ! (değil) işleçlerini kullanabilirsiniz. Simgeleri ve işleçleri parantez içinde de gruplandırabilirsiniz.

#if, , #elif, #endif#defineve #undef yönergeleriyle #elsebirlikte, bir veya daha fazla simgenin varlığına bağlı olarak kodu dahil etmenizi veya hariç tutmanızı sağlar. Koşullu derleme, hata ayıklama derlemesi için kod derlerken veya belirli bir yapılandırma için derleme yaparken yararlı olabilir.

Yönergeyle başlayan bir #if koşullu yönerge, bir yönergeyle #endif açıkça sonlandırılmalıdır. #define bir simge tanımlamanıza olanak tanır. yönergesine #if geçirilen ifade olarak sembolünü kullanarak ifadesi olarak truedeğerlendirilir. DefineConstants derleyici seçeneğiyle bir simge de tanımlayabilirsiniz. ile #undefbir simgenin tanımlarını kaldırabilirsiniz. ile #define oluşturulan bir simgenin kapsamı, tanımlandığı dosyadır. DefineConstants ile veya ile #define tanımladığınız bir simge, aynı ada sahip bir değişkenle çakışmaz. Başka bir ifadeyle, bir değişken adı önişlemci yönergesine geçirilmemelidir ve bir simge yalnızca önişlemci yönergesi tarafından değerlendirilebilir.

#elif bileşik koşullu yönerge oluşturmanıza olanak tanır. yukarıdaki #elif veya herhangi bir önceki #if , isteğe bağlı yönerge ifadeleri olarak değerlendirilirse ifade #elif değerlendirilir true. bir #elif ifade olarak truedeğerlendirilirse, derleyici ile sonraki koşullu yönerge arasındaki #elif tüm kodu değerlendirir. Örnek:

#define VC7
//...
#if DEBUG
    Console.WriteLine("Debug build");
#elif VC7
    Console.WriteLine("Visual Studio 7");
#endif

#elsebileşik bir koşullu yönerge oluşturmanıza olanak tanır; böylece, yukarıdaki #if veya (isteğe bağlı) #elif yönergelerdeki ifadelerden hiçbiri olarak değerlendirilmezsetrue, derleyici ile sonraki #endifarasında #else tüm kodu değerlendirir. #endif(#endif) sonrasındaki #elsesonraki önişlemci yönergesi olmalıdır.

#endif , yönergesiyle başlayan koşullu yönergenin #if sonunu belirtir.

Derleme sistemi, SDK stilindeki projelerde farklı hedef çerçeveleri temsil eden önceden tanımlanmış ön işlemci sembollerinin de farkındadır. Birden fazla .NET sürümünü hedefleyebilecek uygulamalar oluştururken kullanışlıdır.

Hedef Çerçeveler Simgeleri Ek simgeler
(.NET 5+ SDK'larda kullanılabilir)
Platform simgeleri (yalnızca kullanılabilir)
işletim sistemine özgü bir TFM belirttiğinizde)
.NET Framework NETFRAMEWORK, NET48, NET472, NET471, NET47, NET462, NET461, NET46, NET452, NET451, NET45, NET40, NET35, NET20 NET48_OR_GREATER, NET472_OR_GREATER, NET471_OR_GREATER, NET47_OR_GREATER, NET462_OR_GREATER, NET461_OR_GREATER, NET46_OR_GREATER, NET452_OR_GREATER, NET451_OR_GREATER, NET45_OR_GREATER, NET40_OR_GREATER, NET35_OR_GREATER, NET20_OR_GREATER
.NET Standard NETSTANDARD, NETSTANDARD2_1, NETSTANDARD2_0, NETSTANDARD1_6, NETSTANDARD1_5, NETSTANDARD1_4, NETSTANDARD1_3, NETSTANDARD1_2, NETSTANDARD1_1, NETSTANDARD1_0 NETSTANDARD2_1_OR_GREATER, NETSTANDARD2_0_OR_GREATER, NETSTANDARD1_6_OR_GREATER, NETSTANDARD1_5_OR_GREATER, NETSTANDARD1_4_OR_GREATER, NETSTANDARD1_3_OR_GREATER, NETSTANDARD1_2_OR_GREATER, NETSTANDARD1_1_OR_GREATER, NETSTANDARD1_0_OR_GREATER
.NET 5+ (ve .NET Core) NET, NET7_0, NET6_0, NET5_0, NETCOREAPP, NETCOREAPP3_1, NETCOREAPP3_0, NETCOREAPP2_2, NETCOREAPP2_1, NETCOREAPP2_0, NETCOREAPP1_1, NETCOREAPP1_0 NET7_0_OR_GREATER, NET6_0_OR_GREATER, NET5_0_OR_GREATER, NETCOREAPP3_1_OR_GREATER, NETCOREAPP3_0_OR_GREATER, NETCOREAPP2_2_OR_GREATER, NETCOREAPP2_1_OR_GREATER, NETCOREAPP2_0_OR_GREATER, NETCOREAPP1_1_OR_GREATER, NETCOREAPP1_0_OR_GREATER ANDROID, IOS, MACCATALYST, MACOS, TVOS, WINDOWS,
[OS][version] (örneğin IOS15_1),
[OS][version]_OR_GREATER (örneğin IOS15_1_OR_GREATER)

Not

  • Sürümsüz simgeler, hedeflediğiniz sürümden bağımsız olarak tanımlanır.
  • Sürüme özgü simgeler yalnızca hedeflediğiniz sürüm için tanımlanır.
  • Simgeler <framework>_OR_GREATER , hedeflediğiniz sürüm ve önceki tüm sürümler için tanımlanır. Örneğin, .NET Framework 2.0'ı hedefliyorsanız, şu simgeler tanımlanır: NET20, NET20_OR_GREATER, NET11_OR_GREATERve NET10_OR_GREATER.
  • Bunlar MSBuild TargetFramework özelliği ve NuGet tarafından kullanılan hedef çerçeve adlarından (TFM) farklıdır.

Not

Geleneksel, SDK stili olmayan projelerde, visual studio'daki farklı hedef çerçeveler için koşullu derleme simgelerini projenin özellikler sayfaları aracılığıyla el ile yapılandırmanız gerekir.

Önceden tanımlanmış diğer simgeler ve TRACE sabitlerini içerirDEBUG. kullanarak #defineproje için ayarlanan değerleri geçersiz kılabilirsiniz. Örneğin DEBUG simgesi, derleme yapılandırma özelliklerinize ("Hata Ayıklama" veya "Yayın" modu) bağlı olarak otomatik olarak ayarlanır.

Aşağıdaki örnekte, bir dosyada simge tanımlama MYTEST ve ardından ve DEBUG simgelerinin MYTEST değerlerini test etme adımları gösterilmektedir. Bu örneğin çıktısı, projeyi Hata Ayıklama veya Sürüm yapılandırma modunda oluşturup oluşturmadığınıza bağlıdır.

#define MYTEST
using System;
public class MyClass
{
    static void Main()
    {
#if (DEBUG && !MYTEST)
        Console.WriteLine("DEBUG is defined");
#elif (!DEBUG && MYTEST)
        Console.WriteLine("MYTEST is defined");
#elif (DEBUG && MYTEST)
        Console.WriteLine("DEBUG and MYTEST are defined");  
#else
        Console.WriteLine("DEBUG and MYTEST are not defined");
#endif
    }
}

Aşağıdaki örnek, mümkün olduğunda daha yeni API'leri kullanabilmeniz için farklı hedef çerçeveleri nasıl test ettiğinizi gösterir:

public class MyClass
{
    static void Main()
    {
#if NET40
        WebClient _client = new WebClient();
#else
        HttpClient _client = new HttpClient();
#endif
    }
    //...
}

Sembol tanımlama

Koşullu derleme için sembolleri tanımlamak veya tanımlarını silmek için aşağıdaki iki önişlemci yönergesini kullanırsınız:

  • #define: Bir simge tanımlayın.
  • #undef: Simgenin tanımlarını kaldırın.

Simge tanımlamak için kullanırsınız #define . yönergesine #if geçirilen ifade olarak sembolünü kullandığınızda, ifade aşağıdaki örnekte gösterildiği gibi olarak değerlendirilir true:

#define VERBOSE

#if VERBOSE
   Console.WriteLine("Verbose output version");
#endif

Not

yönergesi #define , genellikle C ve C++'da yapılan sabit değerleri bildirmek için kullanılamaz. C# içindeki sabitler en iyi şekilde bir sınıfın veya yapının statik üyeleri olarak tanımlanır. Bu tür çeşitli sabitleriniz varsa, bunları tutmak için ayrı bir "Sabitler" sınıfı oluşturmayı göz önünde bulundurun.

Semboller, derleme koşullarını belirtmek için kullanılabilir. simgesi için veya #elifile #if test edebilirsiniz. Koşullu derleme gerçekleştirmek için de ConditionalAttribute kullanabilirsiniz. Simge tanımlayabilirsiniz, ancak simgeye değer atayamazsınız. Önişlemci #define yönergeleri olmayan yönergeleri kullanmadan önce yönergenin dosyada görünmesi gerekir. DefineConstants derleyici seçeneğiyle bir simge de tanımlayabilirsiniz. ile #undefbir simgenin tanımlarını kaldırabilirsiniz.

Bölgeleri tanımlama

Aşağıdaki iki önişlemci yönergesini kullanarak bir anahatta daraltılabilir kod bölgeleri tanımlayabilirsiniz:

  • #region: Bir bölge başlatın.
  • #endregion: Bir bölgeyi sonlandırma.

#region , kod düzenleyicisinin ana hat özelliğini kullanırken genişletebileceğiniz veya daraltabileceğiniz bir kod bloğu belirtmenize olanak tanır. Daha uzun kod dosyalarında, dosyanın üzerinde çalışmakta olduğunuz bölümüne odaklanabilmeniz için bir veya daha fazla bölgeyi daraltmak veya gizlemek uygundur. Aşağıdaki örnekte bir bölgenin nasıl tanımlanacağı gösterilmektedir:

#region MyClass definition
public class MyClass
{
    static void Main()
    {
    }
}
#endregion

Bir #region bloğun bir #endregion yönergeyle sonlandırılması gerekir. Blok #region , bir #if blokla örtüşemez. Ancak, bir blok bir #region#if bloğun içine yerleştirilebilir ve bir #if blok bir #region bloğun içine iç içe yerleştirilebilir.

Hata ve uyarı bilgileri

Derleyiciye kullanıcı tanımlı derleyici hataları ve uyarıları oluşturmasını ve aşağıdaki yönergeleri kullanarak satır bilgilerini denetlemesini bildirirsiniz:

  • #error: Belirtilen iletiyle bir derleyici hatası oluşturun.
  • #warning: Belirli bir iletiyle bir derleyici uyarısı oluşturun.
  • #line: Derleyici iletileriyle yazdırılan satır numarasını değiştirin.

#error kodunuzda belirli bir konumdan CS1029 kullanıcı tanımlı bir hata oluşturmanıza olanak tanır. Örnek:

#error Deprecated code in this method.

Not

Derleyici özel bir şekilde davranır #error version ve kullanılan derleyici ve dil sürümlerini içeren bir iletiyle birlikte CS8304 derleyici hatasını bildirir.

#warning kodunuzda belirli bir konumdan CS1030 düzeyinde bir derleyici uyarısı oluşturmanızı sağlar. Örnek:

#warning Deprecated code in this method.

#line derleyicinin satır numaralandırmasını ve (isteğe bağlı olarak) hata ve uyarılar için dosya adı çıkışını değiştirmenize olanak tanır.

Aşağıdaki örnek, satır numaralarıyla ilişkili iki uyarının nasıl rapor yapılacağını gösterir. yönergesi, #line 200 sonraki satırın numarasını 200 olarak zorlar (varsayılan değer #6 olmasına rağmen) ve bir sonraki #line yönergeye kadar dosya adı "Özel" olarak bildirilir. yönergesi #line default , önceki yönerge tarafından yeniden numaralandırılan satırları sayan satır numaralandırmasını varsayılan numaralandırmasına döndürür.

class MainClass
{
    static void Main()
    {
#line 200 "Special"
        int i;
        int j;
#line default
        char c;
        float f;
#line hidden // numbering not affected
        string s;
        double d;
    }
}

Derleme aşağıdaki çıkışı üretir:

Special(200,13): warning CS0168: The variable 'i' is declared but never used
Special(201,13): warning CS0168: The variable 'j' is declared but never used
MainClass.cs(9,14): warning CS0168: The variable 'c' is declared but never used
MainClass.cs(10,15): warning CS0168: The variable 'f' is declared but never used
MainClass.cs(12,16): warning CS0168: The variable 's' is declared but never used
MainClass.cs(13,16): warning CS0168: The variable 'd' is declared but never used

yönergesi #line , derleme işleminde otomatik, ara bir adımda kullanılabilir. Örneğin, satırlar özgün kaynak kod dosyasından kaldırıldıysa ancak yine de derleyicinin dosyasındaki özgün satır numaralandırmasına dayalı çıktı oluşturmasını istiyorsanız, satırları kaldırabilir ve ardından ile #lineözgün satır numaralandırmanın benzetimini yapabilirsiniz.

yönergesi #line hidden hata ayıklayıcıdan ardışık satırları gizler; böylece geliştirici kodda adım adım ilerlediğinde, a #line hidden ile sonraki #line yönerge arasındaki tüm satırlar (başka bir #line hidden yönerge olmadığı varsayılarak) aşılır. Bu seçenek, ASP.NET kullanıcı tanımlı kodla makine tarafından oluşturulan kod arasında ayrım yapılmasına izin vermek için de kullanılabilir. bu özelliğin birincil tüketicisi ASP.NET olsa da, büyük olasılıkla daha fazla kaynak oluşturucu bu özelliği kullanacaktır.

Yönerge #line hidden , hata raporlamadaki dosya adlarını veya satır numaralarını etkilemez. Yani, derleyici gizli bir blokta hata bulursa, derleyici hatanın geçerli dosya adını ve satır numarasını bildirir.

yönergesi #line filename , derleyici çıkışında görünmesini istediğiniz dosya adını belirtir. Varsayılan olarak, kaynak kod dosyasının gerçek adı kullanılır. Dosya adı çift tırnak işareti ("") içinde olmalı ve önünde bir satır numarası bulunmalıdır.

C# 10 ile başlayarak yönergesinin #line yeni bir biçimini kullanabilirsiniz:

#line (1, 1) - (5, 60) 10 "partial-class.cs"
/*34567*/int b = 0;

Bu formun bileşenleri şunlardır:

  • (1, 1): Yönergesini izleyen satırdaki ilk karakterin başlangıç satırı ve sütunu. Bu örnekte, sonraki satır 1. satır, sütun 1 olarak bildirilir.
  • (5, 60): İşaretli bölgenin bitiş çizgisi ve sütunu.
  • 10: Yönergenin #line etkili olması için sütun uzaklığı. Bu örnekte, 10. sütun birinci sütun olarak bildirilir. Beyanname int b = 0; burada başlar. Bu alan isteğe bağlıdır. Atlanırsa yönergesi ilk sütunda geçerlilik kazanır.
  • "partial-class.cs": Çıkış dosyasının adı.

Yukarıdaki örnek aşağıdaki uyarıyı oluşturur:

partial-class.cs(1,5,1,6): warning CS0219: The variable 'b' is assigned but its value is never used

Yeniden eşlemeden sonra değişkeni, bdosyasının partial-class.csilk satırında, altıncı karakterdedir.

Etki alanına özgü diller (DLL' ler) genellikle kaynak dosyadan oluşturulan C# çıkışına daha iyi bir eşleme sağlamak için bu biçimi kullanır. Bu genişletilmiş #line yönergenin en yaygın kullanımı, oluşturulan bir dosyada görüntülenen uyarıları veya hataları özgün kaynakla yeniden eşlemektir. Örneğin, şu razor sayfasını göz önünde bulundurun:

@page "/"
Time: @DateTime.NowAndThen

özelliği DateTime.Now olarak DateTime.NowAndThenyanlış yazıldı. Bu razor kod parçacığı için oluşturulan C# öğesinde page.g.csaşağıdaki gibi görünür:

  _builder.Add("Time: ");
#line (2, 6) (2, 27) 15 "page.razor"
  _builder.Add(DateTime.NowAndThen);

Önceki kod parçacığı için derleyici çıkışı:

page.razor(2, 2, 2, 27)error CS0117: 'DateTime' does not contain a definition for 'NowAndThen'

2. satır, 6 page.razor . sütun metnin @DateTime.NowAndThen başladığı yerdir. Bu, yönergesinde tarafından (2, 6) not edilir. Bu aralık @DateTime.NowAndThen 2. satır, sütun 27'de biter. Bu, yönergesinde tarafından (2, 27) not edilir. için DateTime.NowAndThen metin 15 page.g.cs. sütunda başlar. Bu, yönergesinde tarafından 15 not edilir. Tüm bağımsız değişkenleri bir araya getirerek derleyici içindeki konumundaki page.razorhatayı bildirir. Geliştirici, oluşturulan kaynağa değil, doğrudan kaynak kodundaki hataya gidebilir.

Bu biçimin diğer örneklerini görmek için, örnekler bölümündeki özellik belirtimine bakın.

Pragmalar

#pragma derleyiciye, göründüğü dosyanın derlenmesi için özel yönergeler verir. Yönergeler derleyici tarafından desteklenmelidir. Başka bir deyişle, özel ön işleme yönergeleri oluşturmak için kullanamazsınız #pragma .

#pragma pragma-name pragma-arguments

Burada pragma-name tanınan bir pragmanın adı ve pragma-arguments pragma özgü bağımsız değişkenlerdir.

#pragma uyarısı

#pragma warning bazı uyarıları etkinleştirebilir veya devre dışı bırakabilir.

#pragma warning disable warning-list
#pragma warning restore warning-list

Burada warning-list , uyarı numaralarının virgülle ayrılmış listesidir. "CS" ön eki isteğe bağlıdır. Hiçbir uyarı numarası belirtilmediğinde, disable tüm uyarıları devre dışı bırakır ve restore tüm uyarıları etkinleştirir.

Not

Visual Studio'da uyarı numaralarını bulmak için projenizi derleyin ve çıkış penceresinde uyarı numaralarını arayın.

, disable kaynak dosyanın bir sonraki satırından başlayarak geçerlilik kazanır. Uyarı, öğesini izleyen satıra restoregeri yüklenir. Dosyada yoksa restore , uyarılar aynı derlemedeki sonraki dosyaların ilk satırında varsayılan durumlarına geri yüklenir.

// pragma_warning.cs
using System;

#pragma warning disable 414, CS3021
[CLSCompliant(false)]
public class C
{
    int i = 1;
    static void Main()
    {
    }
}
#pragma warning restore CS3021
[CLSCompliant(false)]  // CS3021
public class D
{
    int i = 1;
    public static void F()
    {
    }
}

sağlama toplamını #pragma

ASP.NET sayfalarında hata ayıklamaya yardımcı olması için kaynak dosyalar için sağlama toplamları oluşturur.

#pragma checksum "filename" "{guid}" "checksum bytes"

Burada "filename" , değişikliklerin veya güncelleştirmelerin izlenmesini gerektiren dosyanın adı, "{guid}" karma algoritmasının Genel Benzersiz Tanımlayıcısı (GUID) ve "checksum_bytes" sağlama toplamının baytlarını temsil eden onaltılık basamak dizesidir. Çift sayıda onaltılık basamak olmalıdır. Tek sayıda basamak, derleme zamanı uyarısıyla sonuçlanır ve yönergesi yoksayılır.

Visual Studio hata ayıklayıcısı her zaman doğru kaynağı bulduğundan emin olmak için bir sağlama toplamı kullanır. Derleyici bir kaynak dosyanın sağlama toplamını hesaplar ve ardından çıkışı program veritabanı (PDB) dosyasına yayar. Ardından hata ayıklayıcı, kaynak dosya için hesaplandığı sağlama toplamıyla karşılaştırmak için PDB'yi kullanır.

Hesaplanan sağlama toplamı .aspx dosyası yerine oluşturulan kaynak dosyaya yönelik olduğundan bu çözüm ASP.NET projelerde çalışmaz. Bu sorunu gidermek için ASP.NET #pragma checksum sayfaları için sağlama toplamı desteği sağlar.

Visual C# içinde bir ASP.NET projesi oluşturduğunuzda, oluşturulan kaynak dosya kaynağın oluşturulduğu .aspx dosyası için bir sağlama toplamı içerir. Derleyici daha sonra bu bilgileri PDB dosyasına yazar.

Derleyici dosyasında bir #pragma checksum yönerge bulamazsa sağlama toplamını hesaplar ve değeri PDB dosyasına yazar.

class TestClass
{
    static int Main()
    {
        #pragma checksum "file.cs" "{406EA660-64CF-4C82-B6F0-42D48172A799}" "ab007f1d23d9" // New checksum
    }
}