C# derleyicisi tarafından yorumlanan çeşitli öznitelikler

, , , , AsyncMethodBuilder, InterpolatedStringHandler, , ModuleInitializerve Experimental öznitelikleriConditional, kodunuzdaki AttributeUsageöğelere uygulanabilir. Obsolete Bu öğelere anlamsal anlam eklerler. Derleyici, çıkışını değiştirmek ve kodunuzu kullanan geliştiriciler tarafından yapılan olası hataları bildirmek için bu anlamsal anlamları kullanır.

Conditional özniteliği

özniteliği, Conditional bir yöntemin yürütülmesini ön işleme tanımlayıcıya bağımlı hale getirir. Conditional özniteliği için ConditionalAttributebir diğer addır ve bir yönteme veya öznitelik sınıfına uygulanabilir.

Aşağıdaki örnekte, Conditional programa özgü tanılama bilgilerinin görüntülenmesini etkinleştirmek veya devre dışı bırakmak için bir yönteme uygulanır:

#define TRACE_ON
using System.Diagnostics;

namespace AttributeExamples;

public class Trace
{
    [Conditional("TRACE_ON")]
    public static void Msg(string msg)
    {
        Console.WriteLine(msg);
    }
}

public class TraceExample
{
    public static void Main()
    {
        Trace.Msg("Now in Main...");
        Console.WriteLine("Done.");
    }
}

TRACE_ON Tanımlayıcı tanımlanmamışsa izleme çıkışı görüntülenmez. Etkileşimli pencerede kendiniz keşfedin.

Conditional Özniteliği genellikle aşağıdaki örnekte gösterildiği gibi sürüm derlemelerinde değil, hata ayıklama derlemelerinde izleme ve günlüğe kaydetme özelliklerini etkinleştirmek için tanımlayıcıyla birlikte DEBUG kullanılır:

[Conditional("DEBUG")]
static void DebugMethod()
{
}

Koşullu olarak işaretlenmiş bir yöntem çağrıldığında, belirtilen ön işleme simgesinin varlığı veya yokluğu derleyicinin yöntemine çağrıları içerip içermediğini veya atlayıp atlamayacağını belirler. Simge tanımlanmışsa çağrı eklenir; aksi takdirde çağrı atlanır. Koşullu yöntem, bir sınıf veya yapı bildiriminde bir yöntem olmalı ve dönüş türüne sahip void olmalıdır. Kullanmak Conditional blokların içindeki #if…#endif yöntemleri kapsayan yöntemlerden daha temiz, daha zarif ve daha az hataya eğilimli bir yöntemdir.

Bir yöntemin birden çok Conditional özniteliği varsa, bir veya daha fazla koşullu simge tanımlanmışsa derleyici yöntemine çağrılar içerir (simgeler OR işleci kullanılarak mantıksal olarak birbirine bağlanır). Aşağıdaki örnekte, veya B varlığının A bir yöntem çağrısına neden olması:

[Conditional("A"), Conditional("B")]
static void DoIfAorB()
{
    // ...
}

Öznitelik sınıflarıyla kullanma Conditional

Özniteliği bir Conditional öznitelik sınıfı tanımına da uygulanabilir. Aşağıdaki örnekte, özel öznitelik Documentation tanımlanmışsa DEBUG meta veriye bilgi ekler.

[Conditional("DEBUG")]
public class DocumentationAttribute : System.Attribute
{
    string text;

    public DocumentationAttribute(string text)
    {
        this.text = text;
    }
}

class SampleClass
{
    // This attribute will only be included if DEBUG is defined.
    [Documentation("This method displays an integer.")]
    static void DoWork(int i)
    {
        System.Console.WriteLine(i.ToString());
    }
}

Obsolete özniteliği

Obsolete özniteliği bir kod öğesini artık kullanılması önerilmez olarak işaretler. Kullanım dışı olarak işaretlenen bir varlığın kullanılması bir uyarı veya hata oluşturur. özniteliği Obsolete tek kullanımlık bir özniteliktir ve özniteliklere izin veren herhangi bir varlığa uygulanabilir. Obsolete , için ObsoleteAttributebir diğer addır.

Aşağıdaki örnekte özniteliği sınıfına ObsoleteA ve yöntemine B.OldMethoduygulanır. uygulanan öznitelik oluşturucusunun B.OldMethod ikinci bağımsız değişkeni olarak ayarlandığından true, bu yöntem derleyici hatasına neden olurken, sınıfın A kullanılması bir uyarı üretir. B.NewMethodAncak çağrısı hiçbir uyarı veya hata üretmez. Örneğin, önceki tanımlarla kullandığınızda, aşağıdaki kod iki uyarı ve bir hata oluşturur:


namespace AttributeExamples
{
    [Obsolete("use class B")]
    public class A
    {
        public void Method() { }
    }

    public class B
    {
        [Obsolete("use NewMethod", true)]
        public void OldMethod() { }

        public void NewMethod() { }
    }

    public static class ObsoleteProgram
    {
        public static void Main()
        {
            // Generates 2 warnings:
            A a = new A();

            // Generate no errors or warnings:
            B b = new B();
            b.NewMethod();

            // Generates an error, compilation fails.
            // b.OldMethod();
        }
    }
}

Öznitelik oluşturucusunun ilk bağımsız değişkeni olarak sağlanan dize, uyarı veya hatanın bir parçası olarak görüntülenir. Sınıf A için iki uyarı oluşturulur: biri sınıf başvurusunun bildirimi için, diğeri de sınıf oluşturucu için. Obsolete özniteliği bağımsız değişken olmadan kullanılabilir, ancak bunun yerine ne kullanılacağına ilişkin bir açıklama da önerilir.

C# 10'da, adların eşleştiğinden nameof emin olmak için sabit dize ilişkilendirmesini ve işlecini kullanabilirsiniz:

public class B
{
    [Obsolete($"use {nameof(NewMethod)} instead", true)]
    public void OldMethod() { }

    public void NewMethod() { }
}

Experimental özniteliği

C# 12'de başlayarak, türler, yöntemler ve derlemeler deneysel bir özelliği göstermek için ile System.Diagnostics.CodeAnalysis.ExperimentalAttribute işaretlenebilir. ile ek açıklamalı bir yönteme veya türe erişerseniz derleyici bir uyarı oluşturur ExperimentalAttribute. Özniteliğiyle işaretlenmiş bir derlemede veya modülde Experimental bildirilen tüm türler deneyseldir. Bunlardan herhangi birine erişirseniz derleyici bir uyarı görüntüler. Deneysel bir özelliğin pilotu olmak için bu uyarıları devre dışı bırakabilirsiniz.

Uyarı

Deneysel özellikler değişikliklere tabidir. API'ler değişebilir veya gelecekteki güncelleştirmelerde kaldırılabilir. Deneysel özellikleri dahil etmek, kitaplık yazarlarının gelecekteki gelişime yönelik fikirler ve kavramlar hakkında geri bildirim almalarının bir yoludur. Deneysel olarak işaretlenmiş herhangi bir özelliği kullanırken çok dikkatli olun.

Özellik belirtiminde Experimentalözniteliği hakkında daha fazla ayrıntı okuyabilirsiniz.

SetsRequiredMembers özniteliği

özniteliği, SetsRequiredMembers derleyiciye bir oluşturucunun bu sınıf veya yapıdaki tüm required üyeleri ayarlandığını bildirir. Derleyici, özniteliğine sahip herhangi bir oluşturucunun System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute tüm required üyeleri başlatmış olduğunu varsayar. Böyle bir oluşturucuyu çağıran herhangi bir kodun gerekli üyeleri ayarlamak için nesne başlatıcılara ihtiyacı yoktur. özniteliğini SetsRequiredMembers eklemek öncelikli olarak konumsal kayıtlar ve birincil oluşturucular için yararlıdır.

AttributeUsage özniteliği

özniteliği, AttributeUsage özel öznitelik sınıfının nasıl kullanılabileceğini belirler. AttributeUsageAttribute , özel öznitelik tanımlarına uyguladığınız bir özniteliktir. özniteliği şunları AttributeUsage denetlemenizi sağlar:

  • Özniteliğin uygulanabileceği program öğeleri. Kullanımını kısıtlamadığınız sürece, aşağıdaki program öğelerinin herhangi birine bir öznitelik uygulanabilir:
    • Bütünleştirilmiş Kod
    • Modül
    • Alan
    • Etkinlik
    • Metot
    • Param
    • Özellik
    • İade
    • Tür
  • Bir özniteliğin tek bir program öğesine birden çok kez uygulanıp uygulanamayacağı.
  • Türetilmiş sınıfların öznitelikleri devralıp devralmadığı.

Varsayılan ayarlar açıkça uygulandığında aşağıdaki örneğe benzer:

[AttributeUsage(AttributeTargets.All,
                   AllowMultiple = false,
                   Inherited = true)]
class NewAttribute : Attribute { }

Bu örnekte sınıfı desteklenen NewAttribute herhangi bir program öğesine uygulanabilir. Ancak her varlığa yalnızca bir kez uygulanabilir. Türetilmiş sınıflar bir temel sınıfa uygulanan özniteliği devralır.

AllowMultiple ve Inherited bağımsız değişkenleri isteğe bağlıdır, bu nedenle aşağıdaki kod aynı etkiye sahiptir:

[AttributeUsage(AttributeTargets.All)]
class NewAttribute : Attribute { }

İlk AttributeUsageAttribute bağımsız değişken, numaralandırmanın AttributeTargets bir veya daha fazla öğesi olmalıdır. Aşağıdaki örnekte gösterildiği gibi, OR işleciyle birden çok hedef türü birbirine bağlanabilir:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
class NewPropertyOrFieldAttribute : Attribute { }

Öznitelikler, otomatik olarak atanan bir özelliğin özelliğine veya yedekleme alanına uygulanabilir. özniteliğinde tanımlayıcı belirtmediğiniz field sürece özelliği için geçerlidir. Her ikisi de aşağıdaki örnekte gösterilmiştir:

class MyClass
{
    // Attribute attached to property:
    [NewPropertyOrField]
    public string Name { get; set; } = string.Empty;

    // Attribute attached to backing field:
    [field: NewPropertyOrField]
    public string Description { get; set; } = string.Empty;
}

AllowMultiple Bağımsız değişken isetrue, aşağıdaki örnekte gösterildiği gibi sonuçta elde edilen öznitelik tek bir varlığa birden çok kez uygulanabilir:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
class MultiUse : Attribute { }

[MultiUse]
[MultiUse]
class Class1 { }

[MultiUse, MultiUse]
class Class2 { }

Bu durumda, MultiUseAttribute olarak ayarlandığından trueart arda AllowMultiple uygulanabilir. Birden çok öznitelik uygulamak için gösterilen her iki biçim de geçerlidir.

ise Inheritedfalse, türetilmiş sınıflar özniteliği öznitelikli bir temel sınıftan devralmaz. Örneğin:

[AttributeUsage(AttributeTargets.Class, Inherited = false)]
class NonInheritedAttribute : Attribute { }

[NonInherited]
class BClass { }

class DClass : BClass { }

Bu durumda devralma NonInheritedAttribute yoluyla uygulanmaz DClass .

Bir özniteliğin nereye uygulanacağını belirtmek için bu anahtar sözcükleri de kullanabilirsiniz. Örneğin, tanımlayıcıyı field: kullanarak autoimplemented özelliğinin backing alanına bir öznitelik ekleyebilirsiniz. Alternatif olarak, bir konumsal kayıttan oluşturulan öğelerden herhangi birine öznitelik uygulamak için , property: veya param: tanımlayıcısını da kullanabilirsinizfield:. Örnek için bkz . Özellik tanımı için konumsal söz dizimi.

AsyncMethodBuilder özniteliği

Özniteliğini System.Runtime.CompilerServices.AsyncMethodBuilderAttribute zaman uyumsuz dönüş türü olabilecek bir türe eklersiniz. özniteliği, belirtilen tür bir zaman uyumsuz yöntemden döndürülürken zaman uyumsuz yöntem uygulamasını oluşturan türü belirtir. Özniteliği aşağıdaki AsyncMethodBuilder türe uygulanabilir:

özniteliğinin AsyncMethodBuilder oluşturucusu, ilişkili oluşturucunun türünü belirtir. Oluşturucu aşağıdaki erişilebilir üyeleri uygulamalıdır:

  • Oluşturucunun türünü döndüren statik Create() bir yöntem.

  • Zaman uyumsuz dönüş türünü döndüren okunabilir Task bir özellik.

  • Bir void SetException(Exception) görev hataladığında özel durumu ayarlayan bir yöntem.

  • void SetResult() Görevi tamamlandı olarak işaretleyen ve isteğe bağlı olarak görevin sonucunu ayarlayan veya void SetResult(T result) yöntemi

  • Start Aşağıdaki API imzasını içeren bir yöntem:

    void Start<TStateMachine>(ref TStateMachine stateMachine)
              where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine
    
  • AwaitOnCompleted Aşağıdaki imzaya sahip bir yöntem:

    public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
        where TAwaiter : System.Runtime.CompilerServices.INotifyCompletion
        where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine
    
  • AwaitUnsafeOnCompleted Aşağıdaki imzaya sahip bir yöntem:

          public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
              where TAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion
              where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine
    

.NET tarafından sağlanan aşağıdaki oluşturucuları okuyarak zaman uyumsuz yöntem oluşturucuları hakkında bilgi edinebilirsiniz:

C# 10 ve sonraki sürümlerde özniteliği, oluşturucuyu AsyncMethodBuilder bu tür için geçersiz kılmak üzere zaman uyumsuz bir yönteme uygulanabilir.

InterpolatedStringHandler ve InterpolatedStringHandlerArguments öznitelikleri

C# 10'dan başlayarak, bir türün ilişkilendirilmiş dize işleyicisi olduğunu belirtmek için bu öznitelikleri kullanırsınız. .NET 6 kitaplığı, parametre için bağımsız değişken olarak ilişkilendirilmiş bir dize kullandığınız senaryolar için string zaten içerirSystem.Runtime.CompilerServices.DefaultInterpolatedStringHandler. İlişkili dizelerin nasıl işlendiğini denetlemek istediğiniz başka örnekleriniz de olabilir. System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute İşleyicinizi uygulayan türe uygularsınız. bu türün System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute oluşturucusunun parametrelerine uygularsınız.

İlişkili dize geliştirmeleri için C# 10 özellik belirtiminde ilişkilendirilmiş dize işleyicisi oluşturma hakkında daha fazla bilgi edinebilirsiniz.

ModuleInitializer özniteliği

özniteliği, ModuleInitializer derleme yüklendiğinde çalışma zamanının çağırdığını bir yöntemi işaretler. ModuleInitializer , için ModuleInitializerAttributebir diğer addır.

ModuleInitializer özniteliği yalnızca şu yönteme uygulanabilir:

  • Statiktir.
  • Parametresizdir.
  • void döndürür.
  • veya içeren modülden internalpublicerişilebilir.
  • Genel bir yöntem değildir.
  • genel bir sınıfta yer almıyor.
  • Yerel bir işlev değildir.

ModuleInitializer Özniteliği birden çok yönteme uygulanabilir. Bu durumda, çalışma zamanının onları çağırma sırası belirleyicidir ancak belirtilmez.

Aşağıdaki örnekte birden çok modül başlatıcı yönteminin kullanımı gösterilmektedir. Init1 ve Init2 yöntemleri öncesinde Mainçalışır ve her bir özelliğine Text bir dize ekler. Bu nedenle çalıştırıldığında Main özelliğin Text zaten her iki başlatıcı yönteminden dizeleri vardır.

using System;

internal class ModuleInitializerExampleMain
{
    public static void Main()
    {
        Console.WriteLine(ModuleInitializerExampleModule.Text);
        //output: Hello from Init1! Hello from Init2!
    }
}
using System.Runtime.CompilerServices;

internal class ModuleInitializerExampleModule
{
    public static string? Text { get; set; }

    [ModuleInitializer]
    public static void Init1()
    {
        Text += "Hello from Init1! ";
    }

    [ModuleInitializer]
    public static void Init2()
    {
        Text += "Hello from Init2! ";
    }
}

Kaynak kodu oluşturucularının bazen başlatma kodu oluşturması gerekir. Modül başlatıcılar bu kod için standart bir yer sağlar. Diğer çoğu durumda, modül başlatıcısı yerine statik bir oluşturucu yazmanız gerekir.

SkipLocalsInit özniteliği

özniteliği, SkipLocalsInit derleyicinin meta veriye gönderirken bayrağı ayarlamasını .locals init engeller. SkipLocalsInit özniteliği tek kullanımlık bir özniteliktir ve bir yönteme, özelliğe, sınıfa, yapıya, arabirime veya modüle uygulanabilir ancak derlemeye uygulanamayabilir. SkipLocalsInit , için SkipLocalsInitAttributebir diğer addır.

bayrağı, .locals init CLR'nin bir yöntemde bildirilen tüm yerel değişkenleri varsayılan değerlerine başlatmasına neden olur. Derleyici ayrıca bir değer atamadan önce hiçbir zaman bir değişken kullanmadığınızdan emin olduğundan, .locals init genellikle gerekli değildir. Ancak, ek sıfır başlatmanın, yığında bir dizi ayırmak için stackalloc kullanmanız gibi bazı senaryolarda ölçülebilir performans etkisi olabilir. Bu gibi durumlarda özniteliğini SkipLocalsInit ekleyebilirsiniz. Bir yönteme doğrudan uygulanırsa, öznitelik bu yöntemi ve lambdalar ve yerel işlevler de dahil olmak üzere iç içe tüm işlevlerini etkiler. Bir türe veya modüle uygulanırsa, iç içe yerleştirilmiş tüm yöntemleri etkiler. Bu öznitelik soyut yöntemleri etkilemez, ancak uygulama için oluşturulan kodu etkiler.

Bu öznitelik AllowUnsafeBlocks derleyici seçeneğini gerektirir. Bu gereksinim bazı durumlarda kodun atanmamış belleği görüntüleyebildiğini (örneğin, başlatılmamış yığına ayrılan bellekten okuma) işaret eder.

Aşağıdaki örnekte özniteliğin SkipLocalsInit kullanan stackallocbir yöntem üzerindeki etkisi gösterilmektedir. yöntemi, tamsayı dizisi ayrıldığında bellekte ne varsa görüntüler.

[SkipLocalsInit]
static void ReadUninitializedMemory()
{
    Span<int> numbers = stackalloc int[120];
    for (int i = 0; i < 120; i++)
    {
        Console.WriteLine(numbers[i]);
    }
}
// output depends on initial contents of memory, for example:
//0
//0
//0
//168
//0
//-1271631451
//32767
//38
//0
//0
//0
//38
// Remaining rows omitted for brevity.

Bu kodu kendiniz denemek için .csproj dosyanızda derleyici seçeneğini ayarlayınAllowUnsafeBlocks:

<PropertyGroup>
  ...
  <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

Ayrıca bkz.