Aracılığıyla paylaş


22 Öznitelikler

22.1 Genel

C# dilinin büyük bölümü programcının programda tanımlanan varlıklar hakkında bildirim temelli bilgiler belirtmesini sağlar. Örneğin, bir sınıftaki bir yöntemin erişilebilirliği, method_modifier privatesüslenerek belirtilir.

C# programcıların öznitelikler olarak adlandırılan yeni bildirim temelli bilgi türleri icat etmelerini sağlar. Programcılar daha sonra çeşitli program varlıklarına öznitelik ekleyebilir ve çalışma zamanı ortamında öznitelik bilgilerini alabilir.

Not: Örneğin, bir çerçeve belirli program öğelerine (sınıflar ve yöntemler gibi) yerleştirilebilen bir HelpAttribute öznitelik tanımlayarak bu program öğelerinden belgelerine eşleme sağlayabilir. son not

Öznitelikler, konumsal ve adlandırılmış parametrelere (§22.2.3) sahip olabilecek öznitelik sınıflarının (§22.2) bildirimiyle tanımlanır. Öznitelikler, öznitelik belirtimleri (§22.3) kullanılarak bir C# programındaki varlıklara eklenir ve çalışma zamanında öznitelik örnekleri (§22.4) olarak alınabilir.

22.2 Öznitelik sınıfları

22.2.1 Genel

soyut sınıfından türetilen bir sınıfSystem.Attribute, doğrudan veya dolaylı olarak bir öznitelik sınıfıdır. Öznitelik sınıfının bildirimi, program varlıklarına yerleştirilebilen yeni bir öznitelik türü tanımlar. Kural gereği, öznitelik sınıfları sonekiyle Attributeadlandırılır. Bir özniteliğin kullanımları bu son eki içerebilir veya atlar.

Genel sınıf bildirimi, doğrudan veya dolaylı temel sınıf olarak kullanılmayacaktır System.Attribute .

Örnek:

public class B : Attribute {}
public class C<T> : B {} // Error – generic cannot be an attribute

son örnek

22.2.2 Öznitelik kullanımı

Özniteliği AttributeUsage (§22.5.2), bir öznitelik sınıfının nasıl kullanılabileceğini açıklamak için kullanılır.

AttributeUsage bir öznitelik sınıfının, üzerinde kullanılabileceğini program varlıklarının türlerini belirtmesini sağlayan bir konumsal parametresi (§22.2.3) vardır.

Örnek: Aşağıdaki örnek, yalnızca class_declaration veSimpleAttribute interface_declarationüzerine yerleştirilebilen adlı bir öznitelik sınıfını tanımlar ve özniteliğin Simple çeşitli kullanımlarını gösterir.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
public class SimpleAttribute : Attribute
{ 
    ... 
}

[Simple] class Class1 {...}
[Simple] interface Interface1 {...}

Bu öznitelik adıyla SimpleAttributetanımlanmış olsa da, Attribute bu öznitelik kullanıldığında, sonek atlanabilir ve kısa adıyla Simplesonuçlanabilir. Bu nedenle, yukarıdaki örnek aşağıdakine eşdeğerdir

[SimpleAttribute] class Class1 {...}
[SimpleAttribute] interface Interface1 {...}

son örnek

AttributeUsage adlı bir parametreye (§22.2.3) AllowMultiplesahiptir. Bu parametre, özniteliğin belirli bir varlık için birden çok kez belirtilip belirtilemeyeceğini gösterir. Öznitelik sınıfı için true ise AllowMultiple , bu öznitelik sınıfı çok kullanımlı bir öznitelik sınıfıdır ve bir varlıkta birden çok kez belirtilebilir. Öznitelik sınıfı için false ise veya belirtilmemişse AllowMultiple , bu öznitelik sınıfı tek kullanımlık bir öznitelik sınıfıdır ve bir varlıkta en fazla bir kez belirtilebilir.

Örnek: Aşağıdaki örnek adlı AuthorAttribute çok kullanımlı bir öznitelik sınıfını tanımlar ve özniteliğinin Author iki kullanımına sahip bir sınıf bildirimi gösterir:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class AuthorAttribute : Attribute
{
    public string Name { get; }
    public AuthorAttribute(string name) => Name = name;
}

[Author("Brian Kernighan"), Author("Dennis Ritchie")]
class Class1 
{
    ...
}

son örnek

AttributeUsage adlı başka bir adlandırılmış parametreye (§22.2.3) Inheritedsahiptir. Bu parametre, bir temel sınıfta belirtildiğinde özniteliğin bu temel sınıftan türetilen sınıflar tarafından da devralınıp devralınmadığını gösterir. Bir Inherited öznitelik sınıfı için true ise, bu öznitelik devralınır. Bir Inherited öznitelik sınıfı için false ise, bu öznitelik devralınmıyor demektir. Belirtilmemişse, varsayılan değeri true olur.

Öznitelik sınıfında XAttributeUsage olduğu gibi, öznitelik eklenmemiş

class X : Attribute { ... }

aşağıdakilere eşdeğerdir:

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

22.2.3 Konumsal ve adlandırılmış parametreler

Öznitelik sınıflarının konumsal parametrelerive adlandırılmış parametreleris olabilir. Bir öznitelik sınıfı için her genel örnek oluşturucu, bu öznitelik sınıfı için geçerli bir konumsal parametre dizisi tanımlar. Öznitelik sınıfı için statik olmayan her genel okuma-yazma alanı ve özelliği, öznitelik sınıfı için adlandırılmış bir parametre tanımlar. Bir özelliğin adlandırılmış parametre tanımlaması için, bu özelliğin hem genel alma erişimcisine hem de ortak küme erişimcisine sahip olması gerekir.

Örnek: Aşağıdaki örnek, adlı HelpAttribute bir konumsal parametresi olan ve adlı bir parametresi urlTopicolan bir öznitelik sınıfını tanımlar. Statik ve genel olmasa da, özelliği Url adlandırılmış bir parametre tanımlamaz, çünkü okuma-yazma değildir. Bu özniteliğin iki kullanımları da gösterilir:

[AttributeUsage(AttributeTargets.Class)]
public class HelpAttribute : Attribute
{
    public HelpAttribute(string url) // url is a positional parameter
    { 
        ...
    }

    // Topic is a named parameter
    public string Topic
    { 
        get;
        set;
    }

    public string Url { get; }
}

[Help("http://www.mycompany.com/xxx/Class1.htm")]
class Class1
{
}

[Help("http://www.mycompany.com/xxx/Misc.htm", Topic ="Class2")]
class Class2
{
}

son örnek

22.2.4 Öznitelik parametre türleri

Bir öznitelik sınıfı için konumsal ve adlandırılmış parametre türleri öznitelik parametre türleriyle sınırlıdır; bunlar:

  • Aşağıdaki türlerden biri: , , , , bool, byte, , char, , double, floatintlongsbyteshortstring. uintulongushort
  • türü object.
  • türü System.Type.
  • Sabit listesi türleri.
  • Yukarıdaki türlerin tek boyutlu dizileri.
  • Bu türlerden birine sahip olmayan bir oluşturucu bağımsız değişkeni veya ortak alan, öznitelik belirtiminde konumsal veya adlandırılmış parametre olarak kullanılmamalıdır.

22.3 Öznitelik belirtimi

Öznitelik belirtimi , daha önce tanımlanmış bir özniteliğin bir program varlığına uygulanmasıdır. Öznitelik, program varlığı için belirtilen ek bildirim temelli bilgilerin bir parçasıdır. Öznitelikler genel kapsamda (içeren derleme veya modüldeki öznitelikleri belirtmek için) ve type_declaration s (§14.7), class_member_declarations (§15.3), interface_member_declarations (§15.3) için belirtilebilir 18.4), struct_member_declarations (§16.3), enum_member_declarations (§19.2), accessor_declarations (§15.7.3), event_accessor_ bildirims (§15.8), parameter_listöğeleri (§15.6.2) ve type_parameter_listöğeleri (§15.2.3).

Öznitelikler öznitelik bölümlerinde belirtilir. Öznitelik bölümü, bir veya daha fazla özniteliğin virgülle ayrılmış listesini çevreleyen bir çift köşeli ayraçtan oluşur. Özniteliklerin böyle bir listede belirtilme sırası ve aynı program varlığına eklenen bölümlerin düzenlenme sırası önemli değildir. Örneğin , , [A][B][B][A]ve [A, B] öznitelik belirtimleri [B, A]eşdeğerdir.

global_attributes
    : global_attribute_section+
    ;

global_attribute_section
    : '[' global_attribute_target_specifier attribute_list ']'
    | '[' global_attribute_target_specifier attribute_list ',' ']'
    ;

global_attribute_target_specifier
    : global_attribute_target ':'
    ;

global_attribute_target
    : identifier
    ;

attributes
    : attribute_section+
    ;

attribute_section
    : '[' attribute_target_specifier? attribute_list ']'
    | '[' attribute_target_specifier? attribute_list ',' ']'
    ;

attribute_target_specifier
    : attribute_target ':'
    ;

attribute_target
    : identifier
    | keyword
    ;

attribute_list
    : attribute (',' attribute)*
    ;

attribute
    : attribute_name attribute_arguments?
    ;

attribute_name
    : type_name
    ;

attribute_arguments
    : '(' ')'
    | '(' positional_argument_list (',' named_argument_list)? ')'
    | '(' named_argument_list ')'
    ;

positional_argument_list
    : positional_argument (',' positional_argument)*
    ;

positional_argument
    : argument_name? attribute_argument_expression
    ;

named_argument_list
    : named_argument (','  named_argument)*
    ;

named_argument
    : identifier '=' attribute_argument_expression
    ;

attribute_argument_expression
    : non_assignment_expression
    ;

Üretim global_attribute_target ve aşağıdaki metinde tanımlayıcı, eşitliğin §6.4.3assemblytanımlandığı veya moduledeğerine eşit bir yazım denetimine sahip olmalıdır. Üretim attribute_target ve aşağıdaki metinde tanımlayıcı, yukarıdakiyle aynı eşitlik tanımını kullanarak veya assemblydeğerine eşit module olmayan bir yazım denetimine sahip olmalıdır.

Öznitelik, bir attribute_name ve isteğe bağlı konumsal ve adlandırılmış bağımsız değişkenlerin bir listesinden oluşur. Adlandırılmış bağımsız değişkenlerin önüne konumsal bağımsız değişkenler (varsa) eklenir. Konumsal bağımsız değişken bir attribute_argument_expression oluşur; adlandırılmış bağımsız değişken bir addan, ardından eşittir işaretinden ve ardından basit atamayla aynı kurallarla kısıtlanan bir attribute_argument_expression oluşur. Adlandırılmış bağımsız değişkenlerin sırası önemli değildir.

Not: Kolaylık sağlamak için, bir array_initializer (§17.7) içinde bir virgüle izin verilirken olduğu gibi, bir global_attribute_section ve attribute_section de sondaki virgüle izin verilir. son not

attribute_name bir öznitelik sınıfı tanımlar.

Bir öznitelik genel düzeyde yerleştirildiğinde, bir global_attribute_target_specifier gerekir. global_attribute_target şuna eşit olduğunda:

  • assembly — hedef, içeren derlemedir
  • module — hedef, içeren modüldür

global_attribute_target için başka değere izin verilmez.

Standartlaştırılmış attribute_target adları , , eventfield, , method, param, property, returnve typeşeklindedirtypevar. Bu hedef adları yalnızca aşağıdaki bağlamlarda kullanılmalıdır:

  • event — bir etkinlik.
  • field — bir alan. Alan benzeri bir olay (örneğin, erişimcileri olmayan bir olay) (§15.8.2) ve otomatik olarak uygulanan bir özellik (§15.7.4) de bu hedefe sahip bir özniteliğe sahip olabilir.
  • method — oluşturucu, sonlandırıcı, yöntem, işleç, özellik alma ve ayarlama erişimcileri, dizin oluşturucu erişimcileri alma ve ayarlama ve olay ekleme ve kaldırma erişimcileri. Alan benzeri bir olayın (örneğin, erişimcileri olmayan bir olay) bu hedefe sahip bir özniteliği de olabilir.
  • param — bir özellik kümesi erişimcisi, dizin oluşturucu kümesi erişimcisi, olay ekleme ve kaldırma erişimcileri ve oluşturucu, yöntem ve işleçteki bir parametre.
  • property — bir özellik ve dizin oluşturucu.
  • return — temsilci, yöntem, işleç, özellik alma erişimcisi ve dizin oluşturucu alma erişimcisi.
  • type — temsilci, sınıf, yapı, numaralandırma ve arabirim.
  • typevar — bir tür parametresi.

Belirli bağlamlar birden fazla hedefte özniteliğin belirtimine izin verir. Bir program, bir attribute_target_specifier ekleyerek hedefi açıkça belirtebilir. attribute_target_specifier olmadan bir varsayılan uygulanır, ancak varsayılanı doğrulamak veya geçersiz kılmak için bir attribute_target_specifier kullanılabilir. Bağlamlar aşağıdaki gibi çözümlenir:

  • Temsilci bildirimindeki bir öznitelik için varsayılan hedef temsilcidir. Aksi takdirde attribute_target şuna eşit olduğunda:
    • type — hedef temsilcidir
    • return — hedef, dönüş değeridir
  • Yöntem bildirimindeki bir öznitelik için varsayılan hedef yöntemidir. Aksi takdirde attribute_target şuna eşit olduğunda:
    • method — hedef yöntemidir
    • return — hedef, dönüş değeridir
  • Bir işleç bildirimindeki bir öznitelik için varsayılan hedef işleçtir. Aksi takdirde attribute_target şuna eşit olduğunda:
    • method — hedef işlecidir
    • return — hedef, dönüş değeridir
  • Bir özellik veya dizin oluşturucu bildirimi için get erişimci bildirimindeki bir öznitelik için, varsayılan hedef ilişkili yöntemdir. Aksi takdirde attribute_target şuna eşit olduğunda:
    • method — hedef ilişkili yöntemdir
    • return — hedef, dönüş değeridir
  • Bir özellik veya dizin oluşturucu bildirimi için küme erişimcisinde belirtilen bir öznitelik için, varsayılan hedef ilişkili yöntemdir. Aksi takdirde attribute_target şuna eşit olduğunda:
    • method — hedef ilişkili yöntemdir
    • param — hedef, tek örtük parametredir
  • Otomatik olarak uygulanan özellik bildirimindeki bir öznitelik için varsayılan hedef özelliğidir. Aksi takdirde attribute_target şuna eşit olduğunda:
    • field — hedef, özelliği için derleyici tarafından oluşturulan yedekleme alanıdır
  • Varsayılan hedef, olay bildirimi event_accessor_declarations atlayan bir olay bildiriminde belirtilen öznitelik için. Aksi takdirde attribute_target şuna eşit olduğunda:
    • event — hedef olay bildirimidir
    • field — hedef alanıdır
    • method — hedefler yöntemlerdir
  • Atlanmayan bir olay bildirimi durumunda, varsayılan hedef yöntemi event_accessor_declarations .
    • method — hedef ilişkili yöntemdir
    • param — hedef tek parametredir

Diğer tüm bağlamlarda, bir attribute_target_specifier eklenmesine izin verilir ancak gereksizdir.

Örnek: bir sınıf bildirimi belirticiyi typeiçerebilir veya atlar:

[type: Author("Brian Kernighan")]
class Class1 {}

[Author("Dennis Ritchie")]
class Class2 {}

bitiş örneği.

Bir uygulama, amaçları uygulama tanımlı olan diğer attribute_targetkabul edebilir. Böyle bir attribute_target tanımayan bir uygulama bir uyarı yayınlar ve içeren attribute_section yok sayar.

Kural gereği, öznitelik sınıfları sonekiyle Attributeadlandırılır. bir attribute_name bu son eki içerebilir veya atlayabilir. Özellikle, bir attribute_name aşağıdaki gibi çözümlenir:

  • attribute_name en doğru tanımlayıcısı bir ayrıntılı tanımlayıcı (§6.4.3) ise, attribute_name type_name(§7.8) olarak çözümlenir. Sonuç, türünden System.Attributetüretilmiş bir tür değilse, derleme zamanı hatası oluşur.
  • Yoksa
    • Hatalar gizlenmezseattribute_name type_name (§7.8) olarak çözümlenir. Bu çözüm başarılı olursa ve türünden System.Attribute türetilmiş bir türle sonuçlanırsa, tür bu adımın sonucudur.
    • Karakterler Attribute attribute_name en sağdaki tanımlayıcıya eklenir ve sonuçta elde edilen belirteç dizesi type_name (§7.8) olarak çözümlenir, ancak hatalar gizlenemez. Bu çözüm başarılı olursa ve türünden System.Attribute türetilmiş bir türle sonuçlanırsa, tür bu adımın sonucudur.

Yukarıdaki iki adımdan tam olarak biri türünden System.Attributetüretilirse, bu tür attribute_name sonucudur. Aksi takdirde bir derleme zamanı hatası oluşur.

Örnek: Bu sonekle birlikte ve olmadan bir öznitelik sınıfı bulunursa, bir belirsizlik ve derleme zamanı hata sonuçları vardır. attribute_name en sağ tanımlayıcısı bir ayrıntılı tanımlayıcı (§6.4.3) olacak şekilde yazılırsa, yalnızca son eki olmayan bir öznitelik eşleştirilir ve bu nedenle böyle bir belirsizliğin çözülmesini sağlar. Örnek

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

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

[Example]               // Error: ambiguity
class Class1 {}

[ExampleAttribute]      // Refers to ExampleAttribute
class Class2 {}

[@Example]              // Refers to Example
class Class3 {}

[@ExampleAttribute]     // Refers to ExampleAttribute
class Class4 {}

ve Exampleadlı ExampleAttribute iki öznitelik sınıfı gösterir. özniteliği [Example] belirsizdir, çünkü veya Exampleöğesine başvurabilirExampleAttribute. Ayrıntılı tanımlayıcı kullanmak, bu tür nadir durumlarda tam amacın belirtilmesine olanak tanır. Özniteliği [ExampleAttribute] belirsiz değildir (yine de ! adlı ExampleAttributeAttributebir öznitelik sınıfı varsa olabilir). Sınıfın Example bildirimi kaldırılırsa, her iki öznitelik de adlı ExampleAttributeöznitelik sınıfına aşağıdaki gibi başvurur:

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

[Example]            // Refers to ExampleAttribute
class Class1 {}

[ExampleAttribute]   // Refers to ExampleAttribute
class Class2 {}

[@Example]           // Error: no attribute named “Example”
class Class3 {}

son örnek

Aynı varlıkta birden çok kez tek kullanımlık öznitelik sınıfı kullanmak derleme zamanı hatasıdır.

Örnek: Örnek

[AttributeUsage(AttributeTargets.Class)]
public class HelpStringAttribute : Attribute
{
    public HelpStringAttribute(string value)
    {
        Value = value;
    }

    public string Value { get; }
}
[HelpString("Description of Class1")]
[HelpString("Another description of Class1")]   // multiple uses not allowed
public class Class1 {}

, tek kullanımlık bir öznitelik sınıfı olan ve bildiriminde birden çok kez kullanmaya HelpStringçalıştığından derleme zamanı hatasıyla Class1sonuçlanır.

son örnek

E İfade, aşağıdaki deyimlerin tümü doğruysa bir attribute_argument_expression:

Örnek:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field)]
public class TestAttribute : Attribute
{
    public int P1 { get; set; }

    public Type P2 { get; set; }

    public object P3 { get; set; }
}

[Test(P1 = 1234, P3 = new int[]{1, 3, 5}, P2 = typeof(float))]
class MyClass {}

class C<T> {
    [Test(P2 = typeof(T))] // Error – T not a closed type.
    int x1;

    [Test(P2 = typeof(C<T>))] // Error – C<;T>; not a closed type.
    int x2;

    [Test(P2 = typeof(C<int>))] // Ok
    int x3;

    [Test(P2 = typeof(C<>))] // Ok
    int x4;
}

son örnek

Birden çok bölümde bildirilen bir türün öznitelikleri, her bir parçasının öznitelikleri belirtilmemiş bir sırada birleştirilerek belirlenir. Aynı öznitelik birden çok bölüme yerleştirilirse, bu özniteliğin türünde birden çok kez belirtilmesiyle eşdeğerdir.

Örnek: İki bölüm:

[Attr1, Attr2("hello")]
partial class A {}

[Attr3, Attr2("goodbye")]
partial class A {}

aşağıdaki tek bildirimle eşdeğerdir:

[Attr1, Attr2("hello"), Attr3, Attr2("goodbye")]
class A {}

son örnek

Tür parametrelerindeki öznitelikler aynı şekilde birleştirilir.

22.4 Öznitelik örnekleri

22.4.1 Genel

Öznitelik örneği, çalışma zamanında özniteliği temsil eden bir örnektir. Öznitelik, öznitelik sınıfı, konumsal bağımsız değişkenler ve adlandırılmış bağımsız değişkenlerle tanımlanır. Öznitelik örneği, konumsal ve adlandırılmış bağımsız değişkenlerle başlatılan öznitelik sınıfının bir örneğidir.

Bir öznitelik örneğinin alınması, aşağıdaki alt dallarda açıklandığı gibi hem derleme zamanı hem de çalışma zamanı işlemeyi içerir.

22.4.2 Özniteliğin derlenmesi

E derlemesi, aşağıdaki adımlar aracılığıyla bir derlemede A derlenir:

  • Yeni formun object_creation_expression T(P) derlemek için derleme zamanı işleme adımlarını izleyin. Bu adımlar derleme zamanı hatasına neden olur veya çalışma C zamanında çağrılabilecek bir örnek oluşturucuyu T belirler.
  • Genel erişilebilirliği yoksa C derleme zamanı hatası oluşur.
  • içindeki her ArgN için:
    • named_argument Nametanımlayıcısı Arg
    • Name üzerinde statik olmayan bir okuma-yazma ortak alanı veya özelliği tanımlayacaktır T. Böyle bir alan veya özellik yoksa T derleme zamanı hatası oluşur.
  • positional_argument_listSystem.String

    Not: Örnek olarak, düşük vekil kod birimi tarafından hemen takip edilmeyen yüksek vekil UTF-16 kod birimi içeren bir dize iyi biçimlendirilmemiştir. son not

  • Özniteliğini içeren programın derlenmesi sonucunda derleyici tarafından derleme çıkışında aşağıdaki bilgileri depolayın: öznitelik sınıfı T, üzerindeki Cörnek oluşturucusuT, P , named_argument_listN ve ilişkili program varlığıE, değerleri derleme zamanında tamamen çözümlenir.

22.4.3 Öznitelik örneğinin çalışma zamanı alımı

§22.4.2'de tanımlanan terimler kullanılarak, , T, Cve ile temsil edilen Pve Nile E ilişkilendirilmiş öznitelik örneği aşağıdaki adımlar kullanılarak derlemeden A çalışma zamanında alınabilir:

  • derleme zamanında belirlenen örnek oluşturucusunu ve değerleri kullanarak formunun new T(P)bir C yürütmek için çalışma zamanı işleme adımlarını izleyin. Bu adımlar bir özel durumla sonuçlanır veya örneğini OToluşturur.
  • içindeki her ArgN sırayla:
    • named_argument Nametanımlayıcısı Arg Name üzerinde Ostatik olmayan bir genel okuma-yazma alanı veya özelliği tanımlamazsa, bir özel durum oluşturulur.
    • öğesinin attribute_argument_expression değerlendirmenin Valuesonucu olsunArg.
    • üzerinde Namebir alan tanımlarsaO, bu alanı olarak Valueayarlayın.
    • Aksi takdirde, Name üzerinde Obir özellik tanımlar. Bu özelliği Değer olarak ayarlayın.
    • Sonuç, öznitelik sınıfının positional_argument_list veOT named_argument_listPbaşlatılan bir örneğidir.N

Not: içinde , , TC, P (ve ile Nilişkilendirilen ) E ve belirtip alma AETCP mekanizmasını N depolama Abiçimi ( ve bu nedenle bir öznitelik örneğinin çalışma zamanında nasıl elde edilir) bu belirtim kapsamı dışındadır. son not

Örnek: CLI'nın bir uygulamasında, Help örnek program §22.2.3'te derlenerek oluşturulan derlemedeki öznitelik örnekleri aşağıdaki programla alınabilir:

public sealed class InterrogateHelpUrls
{
    public static void Main(string[] args)
    {
        Type helpType = typeof(HelpAttribute);
        string assemblyName = args[0];
        foreach (Type t in Assembly.Load(assemblyName).GetTypes()) 
        {
            Console.WriteLine($"Type : {t}");
            var attributes = t.GetCustomAttributes(helpType, false);
            var helpers = (HelpAttribute[]) attributes;
            foreach (var helper in helpers)
            {
                Console.WriteLine($"\tUrl : {helper.Url}");
            }
        }
    }
}

son örnek

22.5 Ayrılmış öznitelikler

22.5.1 Genel

Bir dizi öznitelik, dili bir şekilde etkiler. Bu öznitelikler arasında şunlar yer alır:

  • System.AttributeUsageAttribute (§22.5.2), bir öznitelik sınıfının hangi yollarla kullanılabileceğini açıklamak için kullanılır.
  • System.Diagnostics.ConditionalAttribute (§22.5.3), koşullu yöntemleri ve koşullu öznitelik sınıflarını tanımlamak için kullanılan çok kullanımlı bir öznitelik sınıfıdır. Bu öznitelik, koşullu derleme simgesini test ederek bir koşulu gösterir.
  • System.ObsoleteAttribute (§22.5.4), bir üyeyi eski olarak işaretlemek için kullanılır.
  • System.Runtime.CompilerServices.AsyncMethodBuilderAttribute (§22.5.5), zaman uyumsuz bir yöntem için görev oluşturucu oluşturmak için kullanılır.
  • System.Runtime.CompilerServices.CallerLineNumberAttribute (§22.5.6.2), System.Runtime.CompilerServices.CallerFilePathAttribute (§22.5.6.3) ve System.Runtime.CompilerServices.CallerMemberNameAttribute (§22.5.6.4), isteğe bağlı parametrelere çağrı bağlamı hakkında bilgi sağlamak için kullanılır.

Null atanabilir statik analiz öznitelikleri (§22.5.7), null değerler ve null durumlar için oluşturulan uyarıların doğruluğunu iyileştirebilir (§8.9.5).

Yürütme ortamı, C# programının yürütülmesini etkileyen ek uygulama tanımlı öznitelikler sağlayabilir.

22.5.2 AttributeUsage özniteliği

özniteliği AttributeUsage , öznitelik sınıfının nasıl kullanılabileceğini açıklamak için kullanılır.

özniteliğiyle AttributeUsage süslenen bir sınıf, doğrudan veya dolaylı olarak öğesinden System.Attributetüretilir. Aksi takdirde derleme zamanı hatası oluşur.

Not: Bu özniteliği kullanma örneği için bkz . §22.2.2. son not

22.5.3 Koşullu öznitelik

22.5.3.1 Genel

özniteliğiConditional, koşullu yöntemlerin ve koşullu öznitelik sınıflarının tanımını etkinleştirir.

22.5.3.2 Koşullu yöntemler

özniteliğiyle Conditional dekore edilmiş bir yöntem, koşullu bir yöntemdir. Bu nedenle her koşullu yöntem, özniteliklerinde Conditional bildirilen koşullu derleme simgeleriyle ilişkilendirilir.

Örnek:

class Eg
{
    [Conditional("ALPHA")]
    [Conditional("BETA")]
    public static void M()
    {
        // ...
    }
}

Eg.M iki koşullu derleme simgesi ALPHA ve BETAile ilişkili bir koşullu yöntem olarak bildirir.

son örnek

Koşullu yönteme yapılan çağrı, ilişkili koşullu derleme simgelerinden biri veya daha fazlası çağrı noktasında tanımlanırsa dahil edilir, aksi takdirde çağrı atlanır.

Koşullu yöntem aşağıdaki kısıtlamalara tabidir:

  • Koşullu yöntem, class_declaration veya struct_declaration bir yöntem olmalıdır. Öznitelik bir arabirim bildirimindeki Conditional bir yöntemde belirtilirse derleme zamanı hatası oluşur.
  • Koşullu yöntem dönüş türüne voidsahip olmalıdır.
  • Koşullu yöntem değiştirici ile override işaretlenmez. Ancak, koşullu bir yöntem değiştirici ile virtual işaretlenebilir. Böyle bir yöntemin geçersiz kılmaları örtük olarak koşullu olur ve açıkça bir Conditional öznitelikle işaretlenmez.
  • Koşullu yöntem bir arabirim yönteminin uygulaması olmamalıdır. Aksi takdirde derleme zamanı hatası oluşur.
  • Koşullu yöntemin parametreleri çıkış parametreleri olmamalıdır.

Ayrıca, koşullu bir yöntemden temsilci oluşturulursa derleme zamanı hatası oluşur.

Örnek: Örnek

#define DEBUG
using System;
using System.Diagnostics;

class Class1
{
    [Conditional("DEBUG")]
    public static void M()
    {
        Console.WriteLine("Executed Class1.M");
    }
}

class Class2
{
    public static void Test()
    {
        Class1.M();
    }
}

Class1.M koşullu bir yöntem olarak bildirir. Class2's Test yöntemi bu yöntemi çağırır. Koşullu derleme simgesi DEBUG tanımlandığından çağrılırsa Class2.Test çağrısı Myapılır. Simge DEBUG tanımlanmamışsa çağrısı Class2.TestClass1.Myapılmaz.

son örnek

Koşullu bir yönteme yapılan çağrının eklenmesinin veya dışlanmasının, çağrının noktasındaki koşullu derleme sembolleri tarafından denetlendiğini anlamak önemlidir.

Örnek: Aşağıdaki kodda

// File Class1.cs:
using System;
using System.Diagnostics;
class Class1
{
    [Conditional("DEBUG")]
    public static void F()
    {
        Console.WriteLine("Executed Class1.F");
    }
}

// File Class2.cs:
#define DEBUG
class Class2
{
    public static void G()
    {
        Class1.F(); // F is called
    }
}

// File Class3.cs:
#undef DEBUG
class Class3
{
    public static void H()
    {
        Class1.F(); // F is not called
    }
}

sınıfları Class2 ve Class3 her biri, tanımlanıp tanımlanmadığına Class1.F bağlı olarak koşullu olan koşullu yöntemine DEBUGçağrılar içerir. Bu simge bağlamında Class2 tanımlandığından ancak tanımlanmadığından Class3, içindeki çağrısı FClass2 eklenirken içindeki çağrısı FClass3 atlanır.

son örnek

Devralma zincirinde koşullu yöntemlerin kullanılması kafa karıştırıcı olabilir. biçiminden basearacılığıyla base.Mkoşullu bir yönteme yapılan çağrılar, normal koşullu yöntem çağrı kurallarına tabidir.

Örnek: Aşağıdaki kodda

// File Class1.cs
using System;
using System.Diagnostics;
class Class1
{
    [Conditional("DEBUG")]
    public virtual void M() => Console.WriteLine("Class1.M executed");
}

// File Class2.cs
class Class2 : Class1
{
    public override void M()
    {
        Console.WriteLine("Class2.M executed");
        base.M(); // base.M is not called!
    }
}

// File Class3.cs
#define DEBUG
class Class3
{
    public static void Main()
    {
        Class2 c = new Class2();
        c.M(); // M is called
    }
}

Class2 , temel sınıfında tanımlanan öğesine M bir çağrı içerir. Temel yöntem tanımsız olan simgesinin DEBUGvarlığına bağlı olarak koşullu olduğundan bu çağrı atlanır. Bu nedenle, yöntemi yalnızca "Class2.M executed" konsoluna yazar. pp_declaration'ların judicious kullanımı bu tür sorunları ortadan kaldırabilir.

son örnek

22.5.3.3 Koşullu öznitelik sınıfları

Bir veya daha fazla öznitelikle süslenmiş bir öznitelik sınıfı (Conditional), koşullu öznitelik sınıfıdır. Bu nedenle bir koşullu öznitelik sınıfı, özniteliklerinde Conditional bildirilen koşullu derleme simgeleriyle ilişkilendirilir.

Örnek:

[Conditional("ALPHA")]
[Conditional("BETA")]
public class TestAttribute : Attribute {}

TestAttribute, ve ALPHAkoşullu derleme simgeleriyle BETA ilişkili bir koşullu öznitelik sınıfı olarak bildirir.

son örnek

Koşullu özniteliğin öznitelik belirtimleri (§22.3), ilişkili koşullu derleme simgelerinden biri veya daha fazlası belirtim noktasında tanımlandığında dahil edilir, aksi takdirde öznitelik belirtimi atlanır.

Koşullu öznitelik sınıfının öznitelik belirtiminin eklenmesinin veya dışlanmasının belirtim noktasındaki koşullu derleme simgeleri tarafından denetlendiğini unutmayın.

Örnek: Örnekte

// File Test.cs:
using System;
using System.Diagnostics;
[Conditional("DEBUG")]
public class TestAttribute : Attribute {}

// File Class1.cs:
#define DEBUG
[Test] // TestAttribute is specified
class Class1 {}

// File Class2.cs:
#undef DEBUG
[Test] // TestAttribute is not specified
class Class2 {}

ve sınıflarının Class1 her biri, tanımlanıp tanımlanmadığına Class2 bağlı olarak koşullu olan özniteliğiyle Testdekore DEBUG edilmiştir. Bu simge bağlamında Class1 tanımlandığından ancak tanımlanmadığından Class2, üzerindeki Class1 Test özniteliğinin belirtimi dahil edilirken özniteliğin TestClass2 belirtimi atlanır.

son örnek

22.5.4 Eski öznitelik

özniteliği Obsolete , artık kullanılmaması gereken türleri ve türlerin üyelerini işaretlemek için kullanılır.

Bir program Obsolete özniteliğiyle dekore edilmiş bir tür veya üye kullanıyorsa, derleyici bir uyarı veya hata yayınlar. Özellikle, bir derleyici hata parametresi sağlanmazsa veya hata parametresi sağlanıp falsedeğerine sahipse bir uyarı verir. Hata parametresi belirtilirse ve değeri trueolduğunda derleyici bir hata verir.

Örnek: Aşağıdaki kodda

[Obsolete("This class is obsolete; use class B instead")]
class A
{
    public void F() {}
}

class B
{
    public void F() {}
}

class Test
{
    static void Main()
    {
        A a = new A(); // Warning
        a.F();
    }
}

sınıfı A özniteliğiyle Obsolete dekore edilmiştir. 'nin AMain her kullanımı, belirtilen iletiyi içeren bir uyarıyla sonuçlanır: "Bu sınıf eski; yerine sınıfını B kullanın".

son örnek

22.5.5 AsyncMethodBuilder özniteliği

Bu öznitelik §15.15.1'de açıklanmıştır.

22.5.6 Caller-info öznitelikleri

22.5.6.1 Genel

Günlüğe kaydetme ve raporlama gibi amaçlar için, bazen işlev üyesinin çağıran kod hakkında belirli derleme zamanı bilgilerini alması yararlı olabilir. Çağıran-bilgi öznitelikleri, bu tür bilgileri saydam bir şekilde geçirmek için bir yol sağlar.

İsteğe bağlı bir parametre çağıran-bilgi özniteliklerinden biriyle eklendiğinde, bir çağrıda karşılık gelen bağımsız değişkenin atlanması varsayılan parametre değerinin yerinin alınmasına neden olmaz. Bunun yerine, çağrı bağlamı hakkında belirtilen bilgiler varsa, bu bilgiler bağımsız değişken değeri olarak geçirilir.

Örnek:

public void Log(
    [CallerLineNumber] int line = -1,
    [CallerFilePath] string path = null,
    [CallerMemberName] string name = null
)
{
    Console.WriteLine((line < 0) ? "No line" : "Line "+ line);
    Console.WriteLine((path == null) ? "No file path" : path);
    Console.WriteLine((name == null) ? "No member name" : name);
}

Bağımsız değişken içermeyen bir çağrısı Log() , çağrının satır numarasını ve dosya yolunun yanı sıra çağrının gerçekleştiği üyenin adını yazdırır.

son örnek

Caller-info öznitelikleri, temsilci bildirimleri de dahil olmak üzere isteğe bağlı parametrelerde her yerde oluşabilir. Ancak, belirli caller-info özniteliklerinin öznitelikleri, ilişkilendirebilecekleri parametre türleri üzerinde kısıtlamalara sahiptir, böylece her zaman yerine alınan bir değerden parametre türüne örtük bir dönüştürme olur.

Kısmi yöntem bildiriminin hem tanımlama hem de uygulama bölümünün parametresinde aynı caller-info özniteliğine sahip olmak bir hatadır. Yalnızca tanımlama bölümündeki caller-info öznitelikleri uygulanırken, yalnızca uygulayan bölümde oluşan caller-info öznitelikleri yoksayılır.

Çağıran bilgileri aşırı yükleme çözümlemesini etkilemez. Öznitelikli isteğe bağlı parametreler çağıranın kaynak kodundan atlandığından aşırı yükleme çözümlemesi, atlanan diğer isteğe bağlı parametreleri (§12.6.4) yoksaydığı gibi bu parametreleri de yoksayar.

Çağıran bilgileri yalnızca bir işlev kaynak kodunda açıkça çağrıldığında değiştirilir. Örtük üst oluşturucu çağrıları gibi örtük çağrıların kaynak konumu yoktur ve arayan bilgilerini değiştirmez. Ayrıca, dinamik olarak bağlı olan çağrılar arayan bilgilerini değiştirmez. Bu gibi durumlarda caller-info öznitelikli bir parametre atlandığında, bunun yerine parametrenin belirtilen varsayılan değeri kullanılır.

Bir özel durum sorgu ifadeleridir. Bunlar söz dizimsel genişletmeler olarak kabul edilir ve genişlettikleri çağrılar, arayan-bilgi öznitelikleriyle isteğe bağlı parametreleri atlayacak şekilde genişletilirse, arayan bilgilerinin yerini alır. Kullanılan konum, çağrının oluşturulduğu sorgu yan tümcesinin konumudur.

Belirli bir parametrede birden fazla caller-info özniteliği belirtilirse, bunlar şu sırayla tanınır: CallerLineNumber, , CallerFilePathCallerMemberName. Aşağıdaki parametre bildirimini göz önünde bulundurun:

[CallerMemberName, CallerFilePath, CallerLineNumber] object p = ...

CallerLineNumber öncelik alır ve diğer iki öznitelik yoksayılır. Atlanırsa CallerLineNumber öncelik CallerFilePath kazanır ve CallerMemberName yoksayılır. Bu özniteliklerin sözcük temelli sıralaması ilgisizdir.

22.5.6.2 CallerLineNumber özniteliği

Sabit değerden System.Runtime.CompilerServices.CallerLineNumberAttribute parametrenin türüne standart bir örtük dönüştürme (§10.4.2) olduğunda isteğe bağlı parametrelerde özniteliğine int.MaxValue izin verilir. Bu, bu değere kadar olan negatif olmayan herhangi bir satır numarasının hatasız geçirilmesini sağlar.

Kaynak kodundaki bir konumdan gelen bir işlev çağrısı, ile isteğe bağlı bir parametreyi CallerLineNumberAttributeatlarsa, varsayılan parametre değeri yerine çağrıya bağımsız değişken olarak bu konumun satır numarasını temsil eden sayısal sabit değer kullanılır.

Çağrı birden çok satıra yayılıyorsa, seçilen satır uygulamaya bağımlıdır.

Satır numarası yönergelerden #line etkilenebilir (§6.5.8).

22.5.6.3 CallerFilePath özniteliği

Parametresinin türünden standart örtük dönüştürme (System.Runtime.CompilerServices.CallerFilePathAttribute) olduğunda isteğe bağlı parametrelerde özniteliğine string izin verilir.

Kaynak kodundaki bir konumdan yapılan işlev çağrısı, ile isteğe bağlı bir parametreyi CallerFilePathAttributeatlarsa, bu konumun dosya yolunu temsil eden bir dize sabit değeri, varsayılan parametre değeri yerine çağrıya bağımsız değişken olarak kullanılır.

Dosya yolunun biçimi uygulamaya bağlıdır.

Dosya yolu yönergelerden etkilenebilir #line (§6.5.8).

22.5.6.4 CallerMemberName özniteliği

Parametresinin türünden standart örtük dönüştürme (System.Runtime.CompilerServices.CallerMemberNameAttribute) olduğunda isteğe bağlı parametrelerde özniteliğine string izin verilir.

İşlev üyesinin gövdesindeki bir konumdan veya işlev üyesinin kendisine veya dönüş türüne uygulanan bir öznitelik içindeki bir işlev çağrısı, kaynak kodundaki parametreler veya tür parametreleri ile CallerMemberNameAttributeisteğe bağlı bir parametreyi atlarsa, bu üyenin adını temsil eden bir dize sabit değeri, varsayılan parametre değeri yerine çağrıya bağımsız değişken olarak kullanılır.

Genel yöntemler içinde gerçekleşen çağrılar için, tür parametre listesi olmadan yalnızca yöntem adı kullanılır.

Açık arabirim üyesi uygulamalarında gerçekleşen çağrılar için, önceki arabirim niteliği olmadan yalnızca yöntem adı kullanılır.

Özellik veya olay erişimcileri içinde gerçekleşen çağrılar için, kullanılan üye adı özelliğin veya olayın kendisidir.

Dizin oluşturucu erişimcileri içinde gerçekleşen çağrılar için, kullanılan üye adı, varsa dizin oluşturucu üyesinde (§22.6Item

Alan veya olay başlatıcılar içinde gerçekleşen çağrılar için, kullanılan üye adı başlatılmakta olan alanın veya olayın adıdır.

Örnek oluşturucularının, statik oluşturucuların, sonlandırıcıların ve işleçlerin bildirimleri içinde gerçekleşen çağrılar için, kullanılan üye adı uygulamaya bağlıdır.

22.5.7 Kod analizi öznitelikleri

22.5.7.1 Genel

Bu bölümdeki öznitelikler, null atanabilirlik ve null durum tanılaması (§8.9.5) sağlayan bir derleyiciyi desteklemek için ek bilgi sağlamak için kullanılır. Derleyicinin null durum tanılaması gerçekleştirmesi gerekmez. Bu özniteliklerin varlığı veya yokluğu, bir programın dilini veya davranışını etkilemez. Null durum tanılaması sağlamayan bir derleyici bu özniteliklerin varlığını okuyup yoksayacaktır. Null durum tanılaması sağlayan bir derleyici, tanılamalarını bilgilendirmek için kullandığı bu özniteliklerden herhangi biri için bu bölümde tanımlanan anlamı kullanacaktır.

Kod analizi öznitelikleri ad alanında System.Diagnostics.CodeAnalysisbildirilir.

Öznitelik Anlamı
AllowNull (§22.5.7.2) Null değer atanamayan bir bağımsız değişken null olabilir.
DisallowNull (§22.5.7.3) Boş değer atanabilir bağımsız değişken hiçbir zaman null olmamalıdır.
MaybeNull (§22.5.7.6) Null değer atanamayan bir dönüş değeri null olabilir.
NotNull (§22.5.7.8) Null değer atanabilir dönüş değeri hiçbir zaman null olmaz.
MaybeNullWhen (§22.5.7.7) Yöntem belirtilen bool değeri döndürdüğünde null değer atanamayan bir bağımsız değişken null olabilir.
NotNullWhen (§22.5.7.10) Yöntem belirtilen bool değeri döndürdüğünde null atanabilir bağımsız değişken null olmaz.
NotNullIfNotNull (§22.5.7.9) Belirtilen parametrenin bağımsız değişkeni null değilse, dönüş değeri null değildir.
DoesNotReturn (§22.5.7.4) Bu yöntem hiçbir zaman döndürmez.
DoesNotReturnIf (§22.5.7.5) İlişkili bool parametre belirtilen değere sahipse bu yöntem hiçbir zaman döndürmez.

Aşağıdaki §22.5.7.1 bölümleri koşullu olarak normatiftir.

22.5.7.2 AllowNull özniteliği

Karşılık gelen tür izin vermese bile giriş olarak null değere izin verildiğini belirtir.

Örnek: Makul bir varsayılan değere sahip olduğundan hiçbir zaman döndürülmemiş null aşağıdaki okuma/yazma özelliğini göz önünde bulundurun. Ancak, bir kullanıcı özelliği bu varsayılan değere ayarlamak için küme erişimcisine null verebilir.

#nullable enable
public class X
{
    [AllowNull]
    public string ScreenName
    {
        get => _screenName;
        set => _screenName = value ?? GenerateRandomScreenName();
    }
    private string _screenName = GenerateRandomScreenName();
    private static string GenerateRandomScreenName() => ...;
}

Bu özelliğin küme erişimcisinin aşağıdaki kullanımı göz önünde bulundurulduğunda

var v = new X();
v.ScreenName = null;   // may warn without attribute AllowNull

Özniteliği olmadan, null kabul etmeyen türdeki özellik null değere ayarlanmış gibi göründüğü için derleyici bir uyarı oluşturabilir. özniteliğinin varlığı bu uyarıyı bastırır. son örnek

22.5.7.3 DisallowNull özniteliği

Karşılık gelen tür izin verse bile giriş olarak null değere izin verilmediğini belirtir.

Örnek: Null değerinin varsayılan değer olduğu ancak istemcilerin bunu yalnızca null olmayan bir değere ayarlayabildiği aşağıdaki özelliği göz önünde bulundurun.

#nullable enable
public class X
{
    [DisallowNull]
    public string? ReviewComment
    {
        get => _comment;
        set => _comment = value ?? throw new ArgumentNullException(nameof(value),
           "Cannot set to null");
    }
    private string? _comment = default;
}

Get erişimcisi varsayılan nulldeğerini döndürebileceğinden, derleyici erişimden önce denetlenmesi gerektiği konusunda uyarabilir. Ayrıca çağıranları null olsa da çağıranların bunu açıkça null olarak ayarlamaması gerektiği konusunda uyarır. son örnek

22.5.7.4 DoNotReturn özniteliği

Belirli bir yöntemin hiçbir zaman döndürmediğini belirtir.

Örnek: Aşağıdakileri göz önünde bulundurun:

public class X
{
    [DoesNotReturn]
    private void FailFast() =>
        throw new InvalidOperationException();

    public void SetState(object? containedField)
    {
        if ((!isInitialized) || (containedField == null))
        {
            FailFast();
        }
        // null check not needed.
        _field = containedField;
    }

    private bool isInitialized = false;
    private object _field;
}

özniteliğinin varlığı bir derleyiciye çeşitli yollarla yardımcı olur. İlk olarak, yöntemin özel durum oluşturmadan çıkabileceği bir yol varsa, derleyici bir uyarı verebilir. İkinci olarak, derleyici uygun bir catch bloğu bulunana kadar bu yönteme yapılan çağrıdan sonra herhangi bir kodda null olabilir uyarılarını bastırabilir. Üçüncüsü, erişilemeyen kod hiçbir null durumu etkilemez.

Öznitelik, bu özniteliğin varlığına bağlı olarak erişilebilirliği (§13.2) veya kesin atama (§9.4) analizini değiştirmez. Yalnızca null atanabilirlik uyarılarını etkilemek için kullanılır. son örnek

22.5.7.5 DoNotReturnIf özniteliği

İlişkili bool parametre belirtilen değere sahipse, belirli bir yöntemin hiçbir zaman döndürülmeyeceğini belirtir.

Örnek: Aşağıdakileri göz önünde bulundurun:

#nullable enable
public class X
{
    private void ThrowIfNull([DoesNotReturnIf(true)] bool isNull, string argumentName)
    {
        if (!isNull)
        {
            throw new ArgumentException(argumentName, $"argument {argumentName} can't be null");
        }
    }

    public void SetFieldState(object containedField)
    {
        ThrowIfNull(containedField == null, nameof(containedField));
        // unreachable code when "isInitialized" is false:
        _field = containedField;
    }

    private bool isInitialized = false;
    private object _field = default!;
}

son örnek

22.5.7.6 MaybeNull özniteliği

Null değer atanamayan bir dönüş değerinin null olabileceğini belirtir.

Örnek: Aşağıdaki genel yöntemi göz önünde bulundurun:

#nullable enable
public T? Find<T>(IEnumerable<T> sequence, Func<T, bool> predicate) { ... }

Bu kodun fikri, ile Tstring değiştirilirse T? null atanabilir bir ek açıklamaya dönüşüyor olmasıdır. Ancak, bu kod bir başvuru türü olarak kısıtlanmadığından yasal T değildir. Ancak, bu özniteliğin eklenmesi sorunu çözer:

#nullable enable
[return: MaybeNull]
public T Find<T>(IEnumerable<T> sequence, Func<T, bool> predicate) { ... }

özniteliği, çağıranlara sözleşmenin null atanamaz bir tür anlamına geldiğini bildirir, ancak dönüş değeri aslında olabilir null. son örnek

22.5.7.7 MaybeNullWhen özniteliği

Yöntemin belirtilen null değeri döndürdüğünde null atanamaz bir bağımsız değişkenin olabileceğini bool belirtir. Bu, özniteliğine MaybeNull benzer (§22.5.7.6), ancak belirtilen dönüş değeri için bir parametre içerir.

22.5.7.8 NotNull özniteliği

Yöntemin döndürdüğünde (oluşturma yerine) null atanabilir değerin hiçbir zaman olacağını null belirtir.

Örnek: Aşağıdakileri göz önünde bulundurun:

#nullable enable
public static void ThrowWhenNull([NotNull] object? value, string valueExpression = "") =>
    _ = value ?? throw new ArgumentNullException(valueExpression);

public static void LogMessage(string? message)
{
    ThrowWhenNull(message, nameof(message));
    Console.WriteLine(message.Length);
}

Null başvuru türleri etkinleştirildiğinde, yöntem ThrowWhenNull uyarı olmadan derlenir. Bu yöntem döndürdüğünde bağımsız değişkeninin value olmaması nullgaranti edilir. Ancak null başvuruyla çağrı ThrowWhenNull yapmak kabul edilebilir. son örnek

22.5.7.9 NotNullIfNotNull özniteliği

Belirtilen parametrenin bağımsız değişkeni değilse null bir dönüş değerinin olmadığını nullbelirtir.

Örnek: Dönüş değerinin null durumu, bir veya daha fazla bağımsız değişkenin null durumuna bağlı olabilir. Belirli bağımsız değişkenler null olmadığında ve bir yöntem her zaman null olmayan bir değer döndürdüğünde derleyici analizine yardımcı olmak için NotNullIfNotNull özniteliği kullanılabilir. Aşağıdaki yöntemi göz önünde bulundurun:

#nullable enable
string GetTopLevelDomainFromFullUrl(string url) { ... }

url Bağımsız değişken değilse nullnull döndürülemez. Null atanabilir başvurular etkinleştirildiğinde, API hiçbir zaman null bağımsız değişken kabul etmemesi koşuluyla bu imza düzgün çalışır. Ancak, bağımsız değişken null olabilirse, dönüş değeri de null olabilir. Bu sözleşmeyi doğru ifade etmek için bu yönteme aşağıdaki şekilde açıklama ekleyin:

#nullable enable
[return: NotNullIfNotNull("url")]
string? GetTopLevelDomainFromFullUrl(string? url) { ... }

son örnek

22.5.7.10 NotNullWh özniteliği

Yöntem belirtilen null değeri döndürdüğünde null atanabilir bir bağımsız değişkenin olmayacağı bool belirtir.

Örnek: Kitaplık yöntemiString.IsNullOrEmpty(String), bağımsız değişken boş bir dize olduğunda true döndürürnull. Bu bir null-check biçimidir: Yönteminin döndürdüğünde falseçağıranların bağımsız değişkeni null olarak denetlemesi gerekmez. Bunun gibi bir yöntemi null atanabilir hale getirmek için parametre türünü null atanabilir bir başvuru türü yapın ve NotNullWhen özniteliğini ekleyin:

#nullable enable
bool IsNullOrEmpty([NotNullWhen(false)] string? value) { ... }

son örnek

Birlikte çalışma için 22.6 Öznitelikleri

Diğer dillerle birlikte çalışma için dizin oluşturucu dizine alınan özellikler kullanılarak uygulanabilir. Dizin oluşturucu için öznitelik yoksa IndexerName , ad Item varsayılan olarak kullanılır. özniteliği, IndexerName bir geliştiricinin bu varsayılanı geçersiz kılıp farklı bir ad belirtmesini sağlar.

Örnek: Dizin oluşturucu adı varsayılan olarak şeklindedir Item. Bu, aşağıdaki gibi geçersiz kılınabilir:

[System.Runtime.CompilerServices.IndexerName("TheItem")]
public int this[int index]
{
    get { ... }
    set { ... }
}

Dizin oluşturucunun adı şudur: TheItem.

son örnek