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 egyref
változót úgy kell értelmezni, ahogyanscoped
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. Obsolete
a aliasa.ObsoleteAttribute
Az alábbi példában az attribútum az Obsolete
osztályra A
és a metódusra B.OldMethod
lesz alkalmazva. Mivel az alkalmazott B.OldMethod
attribútumkonstruktor második argumentuma a következőre true
van á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.NewMethod
azonban 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:
- Elérhető
GetAwaiter
metódusa van. - A metódus által visszaadott
GetAwaiter
objektum implementálja az interfészt System.Runtime.CompilerServices.ICriticalNotifyCompletion .
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 vagyvoid 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étA
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:
- System.Runtime.CompilerServices.AsyncTaskMethodBuilder
- System.Runtime.CompilerServices.AsyncTaskMethodBuilder<TResult>
- System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder
- System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder<TResult>
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. ModuleInitializer
a 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. SkipLocalsInit
a 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 stackalloc
metó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 scoped
kezeli a következőtref
:
- A
this
példány metódusainakstruct
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.