Megosztás a következőn keresztül:


A C#-fordító által értelmezett egyéb attribútumok

A kód elemeire számos attribútum alkalmazható, amelyek szemantikai jelentést adnak ezekhez az elemekhez:

  • Conditional: A metódus végrehajtásának függővé tétele egy előfeldolgozó-azonosítótól.
  • Obsolete: Jelölje meg a típust vagy tagot a (lehetséges) jövőbeli eltávolításhoz.
  • AttributeUsage: Deklarálja azokat a nyelvi elemeket, amelyekben attribútum alkalmazható.
  • AsyncMethodBuilder: Deklaráljon egy aszinkron metódusszerkesztő-típust.
  • InterpolatedStringHandler: Definiáljon egy interpolált sztringszerkesztőt egy ismert forgatókönyvhöz.
  • ModuleInitializer: Deklaráljon egy modult inicializáló metódust.
  • SkipLocalsInit: Adja meg a helyi változótárolót 0-ra inicializáló kódot.
  • UnscopedRef: Deklarálja, hogy egy ref változót úgy kell értelmezni, ahogyan scoped azt a rendszer nem értelmezi.
  • OverloadResolutionPriority: Adjon hozzá egy tiebreaker attribútumot a túlterhelés feloldásának befolyásolásához a nem egyértelmű túlterhelések esetén.
  • Experimental: Típus vagy tag megjelölése kísérletiként.

A fordító ezen szemantikai jelentésekkel módosítja a kimenetét, és a kód használatával bejelenti a lehetséges hibákat a fejlesztők számára.

Conditional attribútum

Az Conditional attribútum egy metódus végrehajtását egy előfeldolgozási azonosítótól teszi függővé. Az Conditional attribútum a metódusok vagy attribútumosztályok ConditionalAttributealiasa, és alkalmazható.

Az alábbi példában Conditional a programspecifikus diagnosztikai információk megjelenítésének engedélyezésére vagy letiltására szolgáló metódusra van alkalmazva:

#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.");
    }
}

Ha az TRACE_ON azonosító nincs definiálva, a nyomkövetési kimenet nem jelenik meg. Fedezze fel magát az interaktív ablakban.

Az Conditional attribútumot gyakran használják az azonosítóval a DEBUG hibakeresési buildek nyomkövetési és naplózási funkcióinak engedélyezéséhez, kiadási buildekben azonban nem, ahogy az alábbi példában látható:

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

Feltételesként megjelölt metódus meghívása esetén a megadott előfeldolgozási szimbólum jelenléte vagy hiánya határozza meg, hogy a fordító tartalmaz-e vagy kihagyja-e a metódusra irányuló hívásokat. Ha a szimbólum definiálva van, a hívás is megjelenik; ellenkező esetben a hívás ki van hagyva. A feltételes metódusnak osztály- vagy szerkezetdeklarációban szereplő metódusnak kell lennie, és visszatérési típussal void kell rendelkeznie. A használat Conditional tisztább, elegánsabb és kevésbé hibalehetőséget jelent, mint a metódusok blokkokban való #if…#endif beágyazása.

Ha egy metódus több Conditional attribútummal rendelkezik, a fordító meghívja a metódust, ha egy vagy több feltételes szimbólum van definiálva (a szimbólumok logikailag össze vannak kapcsolva az OR operátor használatával). Az alábbi példában egy metódushívás jelenléte A vagy B eredménye:

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

Használat Conditional attribútumosztályokkal

Az Conditional attribútum attribútumosztály-definícióra is alkalmazható. Az alábbi példában az egyéni attribútum Documentation információkat ad hozzá a metaadatokhoz, ha DEBUG definiálva van.

[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 attribútum

Az Obsolete attribútum már nem ajánlottként jelöli meg a kódelemeket. Az elavultként megjelölt entitás használata figyelmeztetést vagy hibát eredményez. Az Obsolete attribútum egy egyszer használatos attribútum, és bármely olyan entitásra alkalmazható, amely engedélyezi az attribútumokat. Obsoletea aliasa.ObsoleteAttribute

Az alábbi példában az attribútum az Obsolete osztályra A és a metódusra B.OldMethodlesz alkalmazva. Mivel az alkalmazott B.OldMethod attribútumkonstruktor második argumentuma a következőre truevan állítva, ez a metódus fordítási hibát okoz, míg az osztály A használata figyelmeztetést eredményez. A hívás B.NewMethodazonban nem okoz figyelmeztetést vagy hibát. Ha például az előző definíciókkal használja, a következő kód két figyelmeztetést és egy hibát generál:


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();
        }
    }
}

Az attribútumkonstruktor első argumentumaként megadott sztring a figyelmeztetés vagy a hiba részeként jelenik meg. Az osztály A két figyelmeztetést generál: egyet az osztályhivatkozás deklarációjára, egyet pedig az osztálykonstruktorra. Az Obsolete attribútum argumentumok nélkül is használható, de javasolt a magyarázat, hogy mit használjon helyette.

A C# 10-ben a sztringek állandó interpolációja és az nameof operátor használatával biztosíthatja, hogy a nevek egyezzenek:

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

    public void NewMethod() { }
}

Experimental attribútum

A C# 12-től kezdődően a típusok, módszerek és szerelvények megjelölhetők a System.Diagnostics.CodeAnalysis.ExperimentalAttribute kísérleti jellemzők jelzésére. A fordító figyelmeztetést ad ki, ha egy metódushoz fér hozzá, vagy beírja a jegyzetet a ExperimentalAttribute. Az attribútummal Experimental megjelölt szerelvényben vagy modulban deklarált összes típus kísérleti. A fordító figyelmeztetést ad ki, ha ön hozzáfér valamelyikhez. Ezeket a figyelmeztetéseket letilthatja egy kísérleti funkció próbaüzeméhez.

Figyelmeztetés

A kísérleti funkciók változhatnak. Előfordulhat, hogy az API-k megváltoznak, vagy a későbbi frissítésekben el lesznek távolítva. A kísérleti funkciókkal a könyvtárszerzők visszajelzést kaphatnak a jövőbeli fejlesztési ötletekről és fogalmakról. A kísérletiként megjelölt funkciók használatakor fokozott óvatossággal járjon el.

Az attribútumról a Experimental szolgáltatás specifikációjában olvashat bővebben.

SetsRequiredMembers attribútum

Az SetsRequiredMembers attribútum tájékoztatja a fordítót, hogy egy konstruktor beállítja az adott osztály vagy szerkezet összes required tagát. A fordító feltételezi, hogy az attribútummal rendelkező konstruktorok inicializálják az System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute összes required tagot. Az ilyen konstruktort meghívó kódokhoz nincs szükség objektum-inicializálókra a szükséges tagok beállításához. Az SetsRequiredMembers attribútum hozzáadása elsősorban a pozíciórekordok és az elsődleges konstruktorok esetében hasznos.

AttributeUsage attribútum

Az AttributeUsage attribútum határozza meg az egyéni attribútumosztályok használatát. AttributeUsageAttribute az egyéni attribútumdefiníciókra alkalmazott attribútum. Az AttributeUsage attribútum segítségével szabályozhatja a következőket:

  • Mely programelemekre alkalmazható az attribútum. Ha nem korlátozza a használatát, az attribútum a következő programelemek bármelyikére alkalmazható:
    • Szerelvény
    • Modul
    • Mező
    • Esemény
    • Metódus
    • Param
    • Tulajdonság
    • Visszatérés
    • Típus
  • Azt határozza meg, hogy egy attribútum többször is alkalmazható-e egyetlen programelemre.
  • Azt határozza meg, hogy a származtatott osztályok öröklik-e az attribútumokat.

Az alapértelmezett beállítások a következő példához hasonlóan jelennek meg, ha explicit módon alkalmazzák:

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

Ebben a példában az NewAttribute osztály bármely támogatott programelemre alkalmazható. De csak egyszer alkalmazható minden entitásra. A származtatott osztályok öröklik az alaposztályra alkalmazott attribútumot.

Az AllowMultiple argumentumok és Inherited az argumentumok megadása nem kötelező, ezért a következő kódnak ugyanaz a hatása:

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

Az első AttributeUsageAttribute argumentumnak az AttributeTargets enumerálás egy vagy több elemének kell lennie. Az OR operátorral több céltípus is összekapcsolható, ahogy az alábbi példa is mutatja:

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

Az attribútumok alkalmazhatók az autoimplementált tulajdonság tulajdonságára vagy háttérmezőjére. Az attribútum a tulajdonságra vonatkozik, hacsak nem adja meg a field megadót az attribútumon. Mindkettő a következő példában látható:

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;
}

Ha az AllowMultiple argumentum az true, akkor az eredményként kapott attribútum több alkalommal is alkalmazható egyetlen entitásra, ahogyan az alábbi példában látható:

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

[MultiUse]
[MultiUse]
class Class1 { }

[MultiUse, MultiUse]
class Class2 { }

Ebben az esetben többször is alkalmazható, MultiUseAttribute mert AllowMultiple be van állítva.true A több attribútum alkalmazásához megjelenített mindkét formátum érvényes.

Ha Inherited igen false, akkor a származtatott osztályok nem öröklik az attribútumot egy attribútummal rendelkező alaposztályból. Példa:

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

[NonInherited]
class BClass { }

class DClass : BClass { }

Ebben az esetben NonInheritedAttribute a rendszer nem alkalmazza az DClass öröklést.

Ezekkel a kulcsszavakval megadhatja az attribútumok alkalmazási helyét is. A kijelölővel field: például hozzáadhat egy attribútumot egy automatikusan összekapcsolt tulajdonság háttérmezőjéhez. Vagy használhatja az field:, property: vagy param: a kijelölőt, hogy egy attribútumot alkalmazzon a pozíciórekordból létrehozott bármely elemre. Példa: A tulajdonságdefiníció pozíciószintaxisa.

AsyncMethodBuilder attribútum

Az attribútumot olyan típushoz adhatja hozzá System.Runtime.CompilerServices.AsyncMethodBuilderAttribute , amely aszinkron visszatérési típus lehet. Az attribútum azt a típust adja meg, amely az aszinkron metódus implementálását hozza létre, amikor a megadott típus egy aszinkron metódusból lesz visszaadva. Az AsyncMethodBuilder attribútum olyan típusra alkalmazható, amely:

Az attribútum konstruktora AsyncMethodBuilder a társított szerkesztő típusát határozza meg. A szerkesztőnek a következő akadálymentes tagokat kell megvalósítania:

  • Statikus Create() metódus, amely a szerkesztő típusát adja vissza.

  • Task Olvasható tulajdonság, amely az aszinkron visszatérési típust adja vissza.

  • Egy void SetException(Exception) metódus, amely a kivételt állítja be egy feladat hibája esetén.

  • Az void SetResult() a vagy void SetResult(T result) metódus, amely befejezettként jelöli meg a tevékenységet, és opcionálisan beállítja a tevékenység eredményét

  • A Start következő API-aláírással rendelkező metódus:

    void Start<TStateMachine>(ref TStateMachine stateMachine)
              where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine
    
  • Egy AwaitOnCompleted metódus a következő aláírással:

    public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
        where TAwaiter : System.Runtime.CompilerServices.INotifyCompletion
        where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine
    
  • Egy AwaitUnsafeOnCompleted metódus a következő aláírással:

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

Az aszinkron metóduskészítőkről a .NET által biztosított alábbi szerkesztőkről olvashat:

A C# 10-es és újabb verzióiban az AsyncMethodBuilder attribútum alkalmazható egy aszinkron metódusra, hogy felülbírálja a szerkesztőt az adott típushoz.

InterpolatedStringHandler és InterpolatedStringHandlerArguments attribútumok

A C# 10-től kezdődően ezekkel az attribútumokkal adhatja meg, hogy egy típus egy interpolált sztringkezelő. A .NET 6 kódtár már tartalmazza System.Runtime.CompilerServices.DefaultInterpolatedStringHandler azokat a forgatókönyveket, amikor egy paraméter argumentumaként string interpolált sztringet használ. Előfordulhat, hogy más példányokkal szeretné szabályozni az interpolált sztringek feldolgozását. Alkalmazza a System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute kezelőt megvalósító típusra. Alkalmazza a System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute típus konstruktorának paramétereire.

Az interpolált sztringkezelő felépítéséről a C# 10 szolgáltatásspecifikációjában tudhat meg többet az interpolált sztringek fejlesztéseihez.

ModuleInitializer attribútum

Az ModuleInitializer attribútum egy metódust jelöl, amelyet a futtatókörnyezet a szerelvény betöltésekor hív meg. ModuleInitializera aliasa.ModuleInitializerAttribute

Az ModuleInitializer attribútum csak olyan metódusra alkalmazható, amely:

  • Statikus.
  • Paraméter nélküli.
  • A visszaadott érték.void
  • Elérhető a tartalmazó modulból, azaz internal public.
  • Ez nem általános módszer.
  • Nem található általános osztályban.
  • Nem helyi függvény.

Az ModuleInitializer attribútum több metódusra is alkalmazható. Ebben az esetben a futtatókörnyezet meghívásának sorrendje determinisztikus, de nincs megadva.

Az alábbi példa több modul inicializáló metódus használatát szemlélteti. A Init1 metódusok korábban Init2 futnak Main, és mindegyik sztringet ad hozzá a Text tulajdonsághoz. Így futtatáskor Main a Text tulajdonságban már vannak sztringek mindkét inicializáló metódusból.

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! ";
    }
}

A forráskódgenerátoroknak néha inicializálási kódot kell létrehozniuk. A modul inicializálói szabványos helyet biztosítanak a kódhoz. A legtöbb más esetben a modul inicializálója helyett statikus konstruktort kell írnia.

SkipLocalsInit attribútum

Az SkipLocalsInit attribútum megakadályozza, hogy a fordító beállítsa a .locals init jelölőt a metaadatokra való kibocsátásakor. Az SkipLocalsInit attribútum egy egyszer használatos attribútum, amely metódusra, tulajdonságra, osztályra, szerkezetre, felületre vagy modulra alkalmazható, szerelvényre azonban nem. SkipLocalsInita aliasa.SkipLocalsInitAttribute

A .locals init jelölő hatására a CLR inicializálja a metódusban deklarált összes helyi változót az alapértelmezett értékükre. Mivel a fordító gondoskodik arról is, hogy soha ne használjon változót, mielőtt valamilyen értéket rendel hozzá, .locals init általában nincs szükség rá. Az extra nulla inicializálás azonban mérhető teljesítménybeli hatással lehet bizonyos helyzetekben, például amikor a stackalloc használatával foglal le egy tömböt a veremen. Ezekben az esetekben hozzáadhatja az SkipLocalsInit attribútumot. Ha egy metódusra közvetlenül alkalmazva van, az attribútum hatással van a metódusra és annak összes beágyazott függvényére, beleértve a lambdákat és a helyi függvényeket is. Ha egy típusra vagy modulra alkalmazza, az hatással van a beágyazott összes metódusra. Ez az attribútum nem befolyásolja az absztrakt metódusokat, de hatással van a megvalósításhoz létrehozott kódra.

Ehhez az attribútumhoz az AllowUnsafeBlocks fordítóbeállítás szükséges. Ez a követelmény azt jelzi, hogy bizonyos esetekben a kód nem hozzárendelt memóriát tekinthet meg (például nem nem iializált, verem által lefoglalt memóriából való olvasást).

Az alábbi példa az attribútumok egy használt stackallocmetódusra gyakorolt hatását SkipLocalsInit mutatja be. A metódus megjeleníti, hogy mi volt a memóriában az egész számok tömbjének lefoglalásakor.

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

A kód kipróbálásához állítsa be a fordító lehetőséget a AllowUnsafeBlocks .csproj fájlban:

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

UnscopedRef attribútum

Az UnscopedRef attribútum a változó deklarációt nem hatókör nélküliként jelöli meg, ami azt jelenti, hogy a hivatkozás feloldható.

Ezt az attribútumot akkor adja hozzá, ha a fordító implicit módon scopedkezeli a következőtref:

  • A this példány metódusainak struct paramétere.
  • ref típusokra hivatkozó ref struct paraméterek.
  • out Paraméterek.

System.Diagnostics.CodeAnalysis.UnscopedRefAttribute Az elem hatókör nélküliként való alkalmazása.

OverloadResolutionPriority attribútum

Ez OverloadResolutionPriorityAttribute lehetővé teszi, hogy a kódtár-szerzők előnyben részesítsék az egyik túlterhelést a másiknál, ha két túlterhelés nem egyértelmű. Elsődleges felhasználási esete, hogy a kódtár-szerzők jobban írjanak túlterheléseket, miközben továbbra is támogatják a meglévő kódokat megszakítások nélkül.

Hozzáadhat például egy új túlterhelést, amely a memórialefoglalások csökkentésére használható ReadOnlySpan<T> :

[OverloadResolutionPriority(1)]
public void M(params ReadOnlySpan<int> s) => Console.WriteLine("Span");
// Default overload resolution priority of 0
public void M(params int[] a) => Console.WriteLine("Array");

A túlterhelés feloldása a két metódust egyformán jónak tartja egyes argumentumtípusok esetében. Argumentumként int[]az első túlterhelést részesíti előnyben. Ha azt szeretné, hogy a fordító előnyben részesítse a ReadOnlySpan verziót, növelheti a túlterhelés prioritását. Az alábbi példa az attribútum hozzáadásának hatását mutatja be:

var d = new OverloadExample();
int[] arr = [1, 2, 3];
d.M(1, 2, 3, 4); // Prints "Span"
d.M(arr); // Prints "Span" when PriorityAttribute is applied
d.M([1, 2, 3, 4]); // Prints "Span"
d.M(1, 2, 3, 4); // Prints "Span"

A legmagasabb túlterhelési prioritásnál alacsonyabb prioritású túlterhelések el lesznek távolítva az alkalmazható módszerek készletéből. Az attribútum nélküli metódusok túlterhelési prioritása a nulla alapértelmezett értékre van állítva. A kódtár-szerzőknek ezt az attribútumot kell végső megoldásként használniuk egy új és jobb metódus túlterhelése esetén. A kódtár-szerzőknek alapos ismereteket kell tudniuk arról, hogy a túlterhelés feloldása milyen hatással van a jobb módszer kiválasztására. Ellenkező esetben váratlan hibák következhetnek be.

Lásd még