Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Istnieje kilka atrybutów, które można zastosować do elementów w kodzie, które dodają do tych elementów znaczenie semantyczne:
-
Conditional
: wykonaj metodę zależną od identyfikatora preprocesora. -
Obsolete
: Oznacz typ lub element do (potencjalnego) usunięcia w przyszłości. -
Deprecated
: (Windows Foundation) Oznacz typ lub element do (potencjalnego) przyszłego usunięcia. -
Experimental
: oznacz typ lub element członkowski jako eksperymentalny. -
SetsRequiredMembers
: wskazuje, że konstruktor ustawia wszystkie wymagane właściwości. -
AttributeUsage
: zadeklaruj elementy języka, w których można zastosować atrybut. -
AsyncMethodBuilder
: Zadeklaruj typ konstruktora metody asynchronicznej. -
InterpolatedStringHandler
: Zdefiniuj konstruktor ciągów interpolowanych dla znanego scenariusza. -
ModuleInitializer
: zadeklaruj metodę, która inicjuje moduł. -
SkipLocalsInit
: Zredukuj kod inicjujący pamięć zmiennych lokalnych do 0. -
UnscopedRef
: Zadeklaruj, że zmiennaref
zwykle interpretowana jakoscoped
powinna być traktowana jako niezakresowa. -
OverloadResolutionPriority
: Dodaj atrybut rozstrzygający, aby wpłynąć na rozstrzygnięcie przeciążeń w przypadku potencjalnie niejednoznacznych przeciążeń. -
EnumeratorCancellation
: określ parametr tokenu anulowania w asynchronicznym enumeratorze. -
CollectionBuilder
: określ metodę konstruktora dla typu kolekcji, gdy wyrażenie kolekcji jest konwertowane na ten typ kolekcji. -
InlineArray
: określ, że typemstruct
jest tablica śródliniowa . -
IUnknownConstant
: określa, jak należy podać brakujący argument dla parametru domyślnego. -
IDispatchConstant
: określa, jak należy podać brakujący argument dla parametru domyślnego.
Kompilator używa tych semantycznych znaczeń do zmiany danych wyjściowych i zgłaszania możliwych błędów w kodzie używanym przez deweloperów.
Atrybut Conditional
Atrybut Conditional
sprawia, że wykonanie metody jest zależne od identyfikatora przetwarzania wstępnego. Atrybut Conditional
jest aliasem dla ConditionalAttributeelementu i można go zastosować do metody lub klasy atrybutów.
W poniższym przykładzie Conditional
zastosowano metodę w celu włączenia lub wyłączenia wyświetlania informacji diagnostycznych specyficznych dla programu:
#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
Jeśli identyfikator nie jest zdefiniowany, dane wyjściowe śledzenia nie są wyświetlane. Zapoznaj się ze sobą w oknie interaktywnym.
Atrybut Conditional
jest często używany z identyfikatorem DEBUG
aby umożliwić funkcje śledzenia i rejestrowania dla kompilacji debugowych, ale nie w kompilacjach produkcyjnych, jak pokazano w poniższym przykładzie.
[Conditional("DEBUG")]
static void DebugMethod()
{
}
Gdy wywoływana jest metoda oznaczona jako warunkowa, obecność lub brak określonego symbolu przetwarzania wstępnego określa, czy kompilator zawiera lub pomija wywołania metody. Jeśli symbol jest zdefiniowany, wywołanie jest dołączane; w przeciwnym razie jest pomijane. Metoda warunkowa musi być metodą w deklaracji klasy lub struktury i musi mieć typ zwracany void
. Użycie Conditional
jest czystsze, bardziej eleganckie i mniej podatne na błędy niż umieszczanie metod wewnątrz bloków #if…#endif
.
Jeśli metoda ma wiele Conditional
atrybutów, kompilator zawiera wywołania metody, jeśli zdefiniowano co najmniej jeden symbol warunkowy (symbole są logicznie połączone za pomocą operatora OR). W poniższym przykładzie obecność A
lub B
powoduje wywołanie metody:
[Conditional("A"), Conditional("B")]
static void DoIfAorB()
{
// ...
}
Używanie Conditional
z klasami atrybutów
Atrybut Conditional
można również zastosować do definicji klasy atrybutu. W poniższym przykładzie atrybut Documentation
niestandardowy dodaje informacje do metadanych, jeśli DEBUG
jest zdefiniowany.
[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
” i „Deprecated
” atrybut
Atrybut Obsolete
oznacza element kodu, który nie jest już zalecany do użycia. Użycie jednostki oznaczonej jako przestarzałe generuje ostrzeżenie lub błąd. Atrybut Obsolete
jest atrybutem pojedynczego użycia i może być stosowany do dowolnej jednostki, która zezwala na atrybuty.
Obsolete
to alias dla elementu ObsoleteAttribute.
W poniższym przykładzie Obsolete
atrybut jest stosowany do klasy A
i metody B.OldMethod
. Ponieważ drugi argument konstruktora atrybutu zastosowanego do B.OldMethod
jest ustawiony na true
, ta metoda powoduje błąd kompilatora, podczas gdy użycie klasy A
generuje ostrzeżenie. Wywołanie B.NewMethod
nie powoduje ostrzeżenia ani błędu. Jeśli na przykład używasz go z poprzednimi definicjami, następujący kod generuje dwa ostrzeżenia i jeden błąd:
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();
}
}
}
Ciąg podany jako pierwszy argument konstruktora atrybutu jest wyświetlany jako część ostrzeżenia lub błędu. Generowane są dwa ostrzeżenia dla klasy A
: jeden dla deklaracji odwołania do klasy i jeden dla konstruktora klasy. Atrybut Obsolete
może być używany bez argumentów, ale w tym wyjaśnienie, co zamiast tego należy użyć, jest zalecane. Aby upewnić się, że nazwy są zgodne, można użyć interpolacji ciągów stałych i operatora nameof
:
public class B
{
[Obsolete($"use {nameof(NewMethod)} instead", true)]
public void OldMethod() { }
public void NewMethod() { }
}
Biblioteki metadanych programu Windows Foundation używają Windows.Foundation.Metadata.DeprecatedAttribute zamiast ObsoleteAttribute
.
Experimental
atrybuty
Począwszy od języka C# 12, typy, metody i zestawy można oznaczyć za System.Diagnostics.CodeAnalysis.ExperimentalAttribute pomocą elementu , aby wskazać funkcję eksperymentalną. Kompilator wyświetla ostrzeżenie, jeśli uzyskujesz dostęp do metody lub typu z adnotacją za pomocą elementu ExperimentalAttribute. Wszystkie typy zadeklarowane w zestawie lub module oznaczonym atrybutem Experimental
są eksperymentalne. Kompilator wyświetla ostrzeżenie, jeśli uzyskujesz dostęp do któregokolwiek z nich. Możesz wyłączyć te ostrzeżenia, aby pilotować funkcję eksperymentalną.
Ostrzeżenie
Funkcje eksperymentalne podlegają zmianom. Interfejsy API mogą ulec zmianie lub można je usunąć w przyszłych aktualizacjach. Uwzględnienie funkcji eksperymentalnych to sposób na uzyskanie opinii autorów bibliotek na temat pomysłów i pojęć związanych z przyszłym opracowywaniem. Należy zachować szczególną ostrożność w przypadku używania dowolnej funkcji oznaczonej jako eksperymentalna. Więcej informacji na temat sposobu oznaczania interfejsów API jako eksperymentalnych można dowiedzieć się w naszym artykule na temat interfejsów API w wersji zapoznawczej .
Więcej informacji na temat atrybutu Experimental
można znaleźć w specyfikacji funkcji.
Biblioteki metadanych programu Windows Foundation używają Windows.Foundation.Metadata.ExperimentalAttribute, która poprzedza język C# 12.
Atrybut SetsRequiredMembers
Atrybut SetsRequiredMembers
informuje kompilator, że konstruktor ustawia wszystkie required
elementy członkowskie w tej klasie lub strukturze. Kompilator zakłada, że każdy konstruktor z atrybutem System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute inicjuje wszystkie elementy required
członków. Kod, który wywołuje taki konstruktor, nie potrzebuje inicjatorów obiektu do ustawienia wymaganych właściwości. Dodanie atrybutu SetsRequiredMembers
jest przydatne przede wszystkim w przypadku rekordów pozycyjnych i konstruktorów podstawowych.
Atrybut AttributeUsage
Atrybut AttributeUsage
określa, jak można użyć niestandardowej klasy atrybutów.
AttributeUsageAttribute to atrybut stosowany do definicji atrybutów niestandardowych. Atrybut AttributeUsage
umożliwia sterowanie:
- Do których elementów programu można zastosować atrybut. Jeśli nie ograniczysz jego użycia, atrybut można zastosować do dowolnego z następujących elementów programu:
- Montaż
- Moduł
- Pole
- Zdarzenie
- Metoda
- Parametr
- Właściwości
- Powrót
- Typ
- Czy atrybut można zastosować do pojedynczego elementu programu wiele razy.
- Czy klasy pochodne dziedziczą atrybuty.
Ustawienia domyślne wyglądają jak w poniższym przykładzie po zastosowaniu jawnie:
[AttributeUsage(AttributeTargets.All,
AllowMultiple = false,
Inherited = true)]
class NewAttribute : Attribute { }
W tym przykładzie klasę NewAttribute
można zastosować do dowolnego obsługiwanego elementu programu. Można go jednak zastosować tylko raz do każdej jednostki. Klasy pochodne dziedziczą atrybut zastosowany do klasy bazowej.
Argumenty AllowMultiple i Inherited są opcjonalne, więc następujący kod ma taki sam efekt:
[AttributeUsage(AttributeTargets.All)]
class NewAttribute : Attribute { }
Pierwszy AttributeUsageAttribute argument musi być co najmniej jednym elementem AttributeTargets wyliczenia. Wiele typów docelowych można połączyć razem z operatorem OR, jak pokazano w poniższym przykładzie:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
class NewPropertyOrFieldAttribute : Attribute { }
Atrybuty można zastosować do właściwości lub pola zapasowego dla właściwości zaimplementowanej automatycznie. Atrybut ma zastosowanie do właściwości, chyba że określisz specyfikator field
na atrybucie. Oba są wyświetlane w poniższym przykładzie:
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;
}
Jeśli argument jest równy AllowMultiple, wtedy wynikowy atrybut można zastosować więcej niż raz do pojedynczej jednostki, jak pokazano w poniższym przykładzie:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
class MultiUse : Attribute { }
[MultiUse]
[MultiUse]
class Class1 { }
[MultiUse, MultiUse]
class Class2 { }
W takim przypadku MultiUseAttribute
można stosować wielokrotnie, ponieważ AllowMultiple
jest ustawione na true
. Oba formaty wyświetlane do stosowania wielu atrybutów są prawidłowe.
Jeśli Inherited ma false
wartość , klasy pochodne nie dziedziczą atrybutu z przypisanej klasy bazowej. Na przykład:
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
class NonInheritedAttribute : Attribute { }
[NonInherited]
class BClass { }
class DClass : BClass { }
W tym przypadku NonInheritedAttribute
nie jest stosowany do DClass
poprzez dziedziczenie.
Możesz również użyć tych słów kluczowych, aby określić, gdzie ma zostać zastosowany atrybut. Na przykład można użyć specyfikatora field:
, aby dodać atrybut do pola zapasowego automatycznie zaimplementowanej właściwości. Możesz też użyć specyfikatora field:
property:
lub param:
, aby zastosować atrybut do dowolnego elementu wygenerowanego na podstawie rekordu pozycyjnego. Aby zapoznać się z przykładem, zobacz Składnia pozycyjna definicji właściwości.
Atrybut AsyncMethodBuilder
Dodajesz atrybut System.Runtime.CompilerServices.AsyncMethodBuilderAttribute do typu, który może być asynchronicznym typem zwrotnym. Atrybut określa typ, który kompiluje implementację metody asynchronicznej, gdy określony typ jest zwracany z metody asynchronicznej. Atrybut AsyncMethodBuilder
można zastosować do typu, który:
- Ma dostępną
GetAwaiter
metodę. - Obiekt zwracany przez metodę
GetAwaiter
System.Runtime.CompilerServices.ICriticalNotifyCompletion implementuje interfejs.
Konstruktor atrybutu AsyncMethodBuilder
określa typ skojarzonego konstruktora. Konstruktor musi zaimplementować następujące dostępne elementy członkowskie:
Metoda statyczna
Create()
zwracająca typ konstruktora.Właściwość czytelna
Task
zwracająca typ zwracany asynchroniczny.void SetException(Exception)
Metoda, która ustawia wyjątek w przypadku błędów zadania.Metoda
void SetResult()
lubvoid SetResult(T result)
, która oznacza zadanie jako ukończone i opcjonalnie ustawia wynik zadaniaMetoda
Start
z następującym podpisem interfejsu API:public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine
Metoda
SetStateMachine
z następującym podpisem interfejsu API:public void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine stateMachine)
Metoda
AwaitOnCompleted
z następującym podpisem:public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.INotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine
Metoda
AwaitUnsafeOnCompleted
z następującym podpisem:public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine
Aby dowiedzieć się więcej na temat konstruktorów metod asynchronicznych, zapoznaj się z następującymi konstruktorami dostarczonymi przez platformę .NET:
- System.Runtime.CompilerServices.AsyncTaskMethodBuilder
- System.Runtime.CompilerServices.AsyncTaskMethodBuilder<TResult>
- System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder
- System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder<TResult>
Atrybut AsyncMethodBuilder
można zastosować do metody asynchronicznej w celu zastąpienia konstruktora dla tego typu.
InterpolatedStringHandler
i InterpolatedStringHandlerArguments
atrybuty
Te atrybuty służą do określania, że typ jest procedurą obsługi ciągów interpolowanych. Biblioteka .NET 6 już zawiera System.Runtime.CompilerServices.DefaultInterpolatedStringHandler dla scenariuszy, w których jako argument parametru string
używany jest ciąg interpolowany. Mogą istnieć inne wystąpienia, w których chcesz kontrolować sposób przetwarzania ciągów interpolowanych. Zastosuj element System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute do typu, który implementuje Twój obsługiwacz. Zastosuj System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute na parametrach konstruktora tego typu.
Więcej informacji na temat budowania obsługi ciągów interpolowanych można znaleźć w specyfikacji dotyczącej ulepszeń ciągów interpolowanych .
Atrybut ModuleInitializer
Atrybut ModuleInitializer
oznacza metodę wywoływaną przez środowisko uruchomieniowe podczas ładowania zestawu.
ModuleInitializer
to alias dla elementu ModuleInitializerAttribute.
Atrybut ModuleInitializer
można zastosować tylko do metody, która:
- Jest statyczny.
- Jest bez parametrów.
- Zwraca wartość
void
. - Jest dostępny z modułu zawierającego , czyli
internal
.public
- Nie jest metodą ogólną.
- Nie jest zawarta w klasie ogólnej.
- Nie jest funkcją lokalną.
Atrybut ModuleInitializer
można zastosować do wielu metod. W takim przypadku kolejność wywoływana przez środowisko uruchomieniowe jest deterministyczna, ale nie jest określona.
Poniższy przykład ilustruje użycie wielu metod inicjatora modułu. Metody Init1
i Init2
są uruchamiane przed elementem Main
, a każda z nich dodaje ciąg do Text
właściwości . Dlatego gdy Main
działa, właściwość Text
ma już ciągi z obu metod inicjalizatorów.
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! ";
}
}
Generator kodu źródłowego czasami musi generować kod inicjowania. Inicjatory modułów zapewniają standardowe miejsce dla tego kodu. W większości innych przypadków należy napisać konstruktor statyczny zamiast inicjatora modułu.
Atrybut SkipLocalsInit
Atrybut SkipLocalsInit
uniemożliwia kompilatorowi ustawienie flagi .locals init
podczas emitowania do metadanych. Atrybut SkipLocalsInit
jest atrybutem pojedynczego użycia i może być stosowany do metody, właściwości, klasy, struktury, interfejsu lub modułu, ale nie do zestawu.
SkipLocalsInit
to alias dla elementu SkipLocalsInitAttribute.
Flaga .locals init
powoduje, że CLR inicjuje wszystkie zmienne lokalne zadeklarowane w metodzie do ich wartości domyślnych. Ponieważ kompilator upewnia się również, że nigdy nie używasz zmiennej przed przypisaniem do niej pewnej wartości, .locals init
zwykle nie jest to konieczne. Jednak dodatkowa inicjalizacja zerowa może mieć wymierny wpływ na wydajność w niektórych scenariuszach, takich jak użycie obiektu stackalloc do przydzielenia tablicy na stosie. W takich przypadkach można dodać SkipLocalsInit
atrybut . Jeśli atrybut zastosowano bezpośrednio na metodzie, oddziałuje on na tę metodę i wszystkie jej zagnieżdżone funkcje, w tym lambdy i funkcje lokalne. W przypadku zastosowania do typu lub modułu ma wpływ na wszystkie metody zagnieżdżone w nich. Ten atrybut nie ma wpływu na metody abstrakcyjne, ale ma wpływ na kod wygenerowany na potrzeby implementacji.
Ten atrybut wymaga opcji kompilatora AllowUnsafeBlocks . To wymaganie sygnalizuje, że w niektórych przypadkach kod może wyświetlać nieprzypisaną pamięć (na przykład odczytywanie z niezainicjowanej pamięci przydzielonej do stosu).
Poniższy przykład ilustruje wpływ atrybutu SkipLocalsInit
na metodę korzystającą z stackalloc
. Metoda wyświetla zawartość pamięci, która była obecna, gdy tablica liczb całkowitych została przydzielona.
[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.
Aby samodzielnie wypróbować ten kod, ustaw opcję kompilatora AllowUnsafeBlocks
w pliku csproj :
<PropertyGroup>
...
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
Atrybut UnscopedRef
Atrybut UnscopedRef
oznacza deklarację zmiennej jako niezakresową, co oznacza, że odwołanie może uciec.
Dodajesz ten atrybut, gdy kompilator traktuje ref
jako niejawnie scoped
.
- Parametr
this
dlastruct
metod wystąpień. -
ref
parametry odwołujące się doref struct
typów. -
out
Parametry.
Stosowanie oznaczeń System.Diagnostics.CodeAnalysis.UnscopedRefAttribute elementu jako niezakresowego.
Atrybut OverloadResolutionPriority
Dzięki OverloadResolutionPriorityAttribute temu autorzy bibliotek preferują jedno przeciążenie przez inne, gdy dwa przeciążenia mogą być niejednoznaczne. Jego głównym zastosowaniem jest umożliwienie autorom bibliotek pisania wydajniejszych wersji przeciążeń przy jednoczesnym utrzymaniu zgodności z istniejącym kodem.
Można na przykład dodać nowe przeciążenie, które używa ReadOnlySpan<T> do zmniejszenia alokacji pamięci:
[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");
Mechanizm rozwiązywania przeciążeń uznaje dwie metody za jednakowo dobre dla niektórych typów argumentów. W przypadku argumentu parametru int[]
preferuje pierwsze przeciążenie. Aby skłonić kompilator do preferowania wersji ReadOnlySpan
, możesz zwiększyć priorytet tego przeciążenia. W poniższym przykładzie pokazano efekt dodawania atrybutu:
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"
Wszystkie przeciążenia o niższym priorytecie niż najwyższy priorytet przeciążenia są usuwane z zestawu odpowiednich metod. Metody bez tego atrybutu mają priorytet przeciążenia ustawiony na wartość domyślną zero. Autorzy bibliotek powinni używać tego atrybutu w ostateczności podczas dodawania nowego i lepszego przeciążenia metody. Autorzy bibliotek powinni mieć głęboką wiedzę na temat wpływu rozwiązywania przeciążenia na wybór lepszej metody. W przeciwnym razie mogą wynikać nieoczekiwane błędy.
Atrybut Anulowanie Enumeratora
Atrybut System.Runtime.CompilerServices.EnumeratorCancellationAttribute określa, który parametr powinien otrzymać token anulowania z interfejsu API System.Collections.Generic.IAsyncEnumerable<T>.GetAsyncEnumerator(CancellationToken). Jest to część infrastruktury funkcji strumieni asynchronicznych .
Atrybut CollectionBuilder
Atrybut System.Runtime.CompilerServices.CollectionBuilderAttribute określa metodę, która tworzy wystąpienie typu kolekcji z wyrażenia kolekcji . Ten atrybut służy do określania metody, która kompiluje kolekcję. Kompilator generuje kod wywołujący tę metodę, gdy wyrażenie kolekcji jest konwertowane na ten typ.
Atrybut InlineArray
Atrybut System.Runtime.CompilerServices.InlineArrayAttribute oznacza typ jako wbudowaną tablicę . Więcej informacji na temat tej funkcji można znaleźć w artykule dotyczącym structs
, w sekcji dotyczącej tablic wbudowanych .
Atrybuty IUnknownConstant i IDispatchConstant
Atrybuty System.Runtime.CompilerServices.IUnknownConstantAttribute i System.Runtime.CompilerServices.IDispatchConstantAttribute można dodać do parametrów domyślnych, aby wskazać, że brakujący argument powinien zostać podany jako new UnknownWrapper(null)
lub new DispatchWrapper(null)
.