Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
22.1 Umum
Sebagian besar bahasa C# memungkinkan programmer menentukan informasi deklaratif tentang entitas yang ditentukan dalam program. Misalnya, aksesibilitas metode di kelas ditentukan dengan mendekorasinya dengan method_modifier, public
, protected
internal
, dan private
.
C# memungkinkan programmer untuk menciptakan jenis informasi deklaratif baru, yang disebut atribut. Programmer kemudian dapat melampirkan atribut ke berbagai entitas program, dan mengambil informasi atribut di lingkungan run-time.
Catatan: Misalnya, kerangka kerja mungkin menentukan
HelpAttribute
atribut yang dapat ditempatkan pada elemen program tertentu (seperti kelas dan metode) untuk menyediakan pemetaan dari elemen program tersebut ke dokumentasi mereka. catatan akhir
Atribut didefinisikan melalui deklarasi kelas atribut (§22.2), yang dapat memiliki parameter posisi dan nama (§22.2.3). Atribut dilampirkan ke entitas dalam program C# menggunakan spesifikasi atribut (§22.3), dan dapat diambil pada run-time sebagai instans atribut (§22.4).
22.2 Kelas atribut
22.2.1 Umum
Kelas yang berasal dari kelas System.Attribute
abstrak , baik secara langsung maupun tidak langsung, adalah kelas atribut. Deklarasi kelas atribut mendefinisikan jenis atribut baru yang dapat ditempatkan pada entitas program. Menurut konvensi, kelas atribut dinamai dengan akhiran Attribute
. Penggunaan atribut dapat mencakup atau menghilangkan akhiran ini.
Deklarasi kelas generik tidak boleh digunakan System.Attribute
sebagai kelas dasar langsung atau tidak langsung.
Contoh:
public class B : Attribute {} public class C<T> : B {} // Error – generic cannot be an attribute
contoh akhir
22.2.2 Penggunaan atribut
Atribut AttributeUsage
(§22.5.2) digunakan untuk menjelaskan bagaimana kelas atribut dapat digunakan.
AttributeUsage
memiliki parameter posisi (§22.2.3) yang memungkinkan kelas atribut untuk menentukan jenis entitas program tempatnya dapat digunakan.
Contoh: Contoh berikut mendefinisikan kelas atribut bernama
SimpleAttribute
yang dapat ditempatkan pada class_declarationdan interface_declarations saja, dan menunjukkan beberapa penggunaanSimple
atribut.[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] public class SimpleAttribute : Attribute { ... } [Simple] class Class1 {...} [Simple] interface Interface1 {...}
Meskipun atribut ini didefinisikan dengan nama
SimpleAttribute
, ketika atribut ini digunakan,Attribute
akhiran dapat dihilangkan, menghasilkan namaSimple
pendek . Dengan demikian, contoh di atas secara semantik setara dengan yang berikut ini[SimpleAttribute] class Class1 {...} [SimpleAttribute] interface Interface1 {...}
contoh akhir
AttributeUsage
memiliki parameter bernama (§22.2.3), yang disebut AllowMultiple
, yang menunjukkan apakah atribut dapat ditentukan lebih dari sekali untuk entitas tertentu. Jika AllowMultiple
untuk kelas atribut benar, kelas atribut tersebut adalah kelas atribut multi-penggunaan, dan dapat ditentukan lebih dari sekali pada entitas. Jika AllowMultiple
untuk kelas atribut salah atau tidak ditentukan, kelas atribut tersebut adalah kelas atribut sekali pakai, dan dapat ditentukan paling banyak sekali pada entitas.
Contoh: Contoh berikut mendefinisikan kelas atribut multi-penggunaan bernama
AuthorAttribute
dan menunjukkan deklarasi kelas dengan dua penggunaanAuthor
atribut:[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 { ... }
contoh akhir
AttributeUsage
memiliki parameter bernama lain (§22.2.3), yang disebut Inherited
, yang menunjukkan apakah atribut, ketika ditentukan pada kelas dasar, juga diwarisi oleh kelas yang berasal dari kelas dasar tersebut. Jika Inherited
untuk kelas atribut benar, maka atribut tersebut diwariskan. Jika Inherited
untuk kelas atribut salah, atribut tersebut tidak diwariskan. Jika tidak ditentukan, nilai defaultnya adalah true.
Kelas X
atribut yang tidak memiliki atribut yang AttributeUsage
melekat padanya, seperti dalam
class X : Attribute { ... }
setara dengan yang berikut ini:
[AttributeUsage(
AttributeTargets.All,
AllowMultiple = false,
Inherited = true)
]
class X : Attribute { ... }
22.2.3 Parameter posisi dan bernama
Kelas atribut dapat memiliki parameterposisi dan parameterbernama s. Setiap konstruktor instans publik untuk kelas atribut menentukan urutan parameter posisi yang valid untuk kelas atribut tersebut. Setiap bidang baca-tulis publik non-statis dan properti untuk kelas atribut menentukan parameter bernama untuk kelas atribut. Agar properti menentukan parameter bernama, properti tersebut harus memiliki aksesor get publik dan aksesor set publik.
Contoh: Contoh berikut mendefinisikan kelas atribut bernama
HelpAttribute
yang memiliki satu parameter posisi,url
, dan satu parameter bernama,Topic
. Meskipun tidak statis dan publik, propertiUrl
tidak menentukan parameter bernama, karena tidak baca-tulis. Dua penggunaan atribut ini juga ditampilkan:[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 { }
contoh akhir
22.2.4 Jenis parameter atribut
Jenis parameter posisi dan bernama untuk kelas atribut terbatas pada jenis parameter atribut, yaitu:
- Salah satu jenis berikut:
bool
, ,byte
,char
,double
,float
,int
long
,sbyte
, ,short
,string
,uint
,ulong
,ushort
. - Jenis
object
. - Jenis
System.Type
. - Jenis enum.
- Array dimensi tunggal dari jenis di atas.
- Argumen konstruktor atau bidang publik yang tidak memiliki salah satu jenis ini, tidak boleh digunakan sebagai parameter posisi atau bernama dalam spesifikasi atribut.
22.3 Spesifikasi atribut
Spesifikasi atribut adalah aplikasi atribut yang ditentukan sebelumnya ke entitas program. Atribut adalah bagian dari informasi deklaratif tambahan yang ditentukan untuk entitas program. Atribut dapat ditentukan pada cakupan global (untuk menentukan atribut pada rakitan atau modul yang berisi) dan untuk type_declaration (§14,7), class_member_declarations (§15,3), interface_member_declarations (18,4), struct_member_declarations (§16,3), enum_member_declarations (§19,2), accessor_declarations (§15,7,3), event_accessor_ deklarasi(§15,8), elemen parameter_lists (§15,6,2), dan elemen type_parameter_lists (§15.2.3).
Atribut ditentukan dalam bagian atribut. Bagian atribut terdiri dari sepasang kurung siku, yang mengelilingi daftar yang dipisahkan koma dari satu atau beberapa atribut. Urutan di mana atribut ditentukan dalam daftar seperti itu, dan urutan di mana bagian yang dilampirkan ke entitas program yang sama diatur, tidak signifikan. Misalnya, spesifikasi [A][B]
atribut , , [B][A]
[A, B]
, dan [B, A]
setara.
global_attributes
: global_attribute_section+
;
global_attribute_section
: '[' 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_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
;
Untuk global_attribute_target produksi, dan dalam teks di bawah ini, pengidentifikasi harus memiliki ejaan yang sama dengan atau , di mana kesetaraan assembly
yang ditentukan dalam module
. Untuk attribute_target produksi, dan dalam teks di bawah ini, pengidentifikasi harus memiliki ejaan yang tidak sama dengan assembly
atau module
, menggunakan definisi kesetaraan yang sama seperti di atas.
Atribut terdiri dari attribute_name dan daftar opsional argumen posisi dan bernama. Argumen posisi (jika ada) mendahului argumen bernama. Argumen posisi terdiri dari attribute_argument_expression; argumen bernama terdiri dari nama, diikuti dengan tanda sama dengan, diikuti oleh attribute_argument_expression, yang, bersama-sama, dibatasi oleh aturan yang sama dengan penugasan sederhana. Urutan argumen bernama tidak signifikan.
Catatan: Untuk kenyamanan, koma berikutnya diizinkan dalam global_attribute_section dan attribute_section, sama seperti yang diizinkan dalam array_initializer (§17,7). catatan akhir
attribute_name mengidentifikasi kelas atribut.
Saat atribut ditempatkan di tingkat global, global_attribute_target_specifier diperlukan. Saat global_attribute_target sama dengan:
-
assembly
— targetnya adalah rakitan yang berisi -
module
— targetnya adalah modul yang berisi
Tidak ada nilai lain untuk global_attribute_target yang diizinkan.
Nama attribute_target yang distandarkan adalah , , , event
, field
method
, param
, property
, dan return
.type
typevar
Nama target ini hanya akan digunakan dalam konteks berikut:
-
event
— sebuah peristiwa. -
field
— bidang. Peristiwa seperti bidang (yaitu, satu tanpa pengakses) (§15.8.2) dan properti yang diimplementasikan secara otomatis (§15.7.4) juga dapat memiliki atribut dengan target ini. -
method
— konstruktor, finalizer, metode, operator, properti mendapatkan dan mengatur aksesor, pengindeks mendapatkan dan mengatur aksesor, dan peristiwa menambahkan dan menghapus aksesor. Peristiwa seperti bidang (yaitu, satu tanpa aksesor) juga dapat memiliki atribut dengan target ini. -
param
— pengakses set properti, pengakses set pengindeks, pengakses penambahan dan penghapusan peristiwa, dan parameter dalam konstruktor, metode, dan operator. -
property
— properti dan pengindeks. -
return
— delegasi, metode, operator, properti dapatkan aksesor, dan pengindeks mendapatkan aksesor. -
type
— delegasi, kelas, struktur, enum, dan antarmuka. -
typevar
— parameter jenis.
Konteks tertentu mengizinkan spesifikasi atribut pada lebih dari satu target. Program dapat secara eksplisit menentukan target dengan menyertakan attribute_target_specifier. Tanpa attribute_target_specifier default diterapkan, tetapi attribute_target_specifier dapat digunakan untuk mengafirmasi atau mengambil alih default. Konteks diselesaikan sebagai berikut:
- Untuk atribut pada deklarasi delegasi, target default adalah delegasi. Jika tidak, jika attribute_target sama dengan:
-
type
— target adalah delegasi -
return
— target adalah nilai pengembalian
-
- Untuk atribut pada deklarasi metode, target default adalah metode . Jika tidak, jika attribute_target sama dengan:
-
method
— targetnya adalah metode -
return
— target adalah nilai pengembalian
-
- Untuk atribut pada deklarasi operator, target default adalah operator. Jika tidak, jika attribute_target sama dengan:
-
method
— targetnya adalah operator -
return
— target adalah nilai pengembalian
-
- Untuk atribut pada deklarasi dapatkan aksesor untuk deklarasi properti atau pengindeks, target default adalah metode terkait. Jika tidak, jika attribute_target sama dengan:
-
method
— target adalah metode terkait -
return
— target adalah nilai pengembalian
-
- Untuk atribut yang ditentukan pada aksesor yang ditetapkan untuk deklarasi properti atau pengindeks, target default adalah metode terkait. Jika tidak, jika attribute_target sama dengan:
-
method
— target adalah metode terkait -
param
— target adalah parameter implisit kesepian
-
- Untuk atribut pada deklarasi properti yang diimplementasikan secara otomatis, target default adalah properti . Jika tidak, jika attribute_target sama dengan:
-
field
— target adalah bidang backing yang dihasilkan kompilator untuk properti
-
- Untuk atribut yang ditentukan pada deklarasi peristiwa yang menghilangkan event_accessor_declarations target default adalah deklarasi peristiwa. Jika tidak, jika attribute_target sama dengan:
-
event
— targetnya adalah deklarasi peristiwa -
field
— target adalah bidang -
method
— targetnya adalah metode
-
- Dalam kasus deklarasi peristiwa yang tidak menghilangkan event_accessor_declarations target default adalah metode .
-
method
— target adalah metode terkait -
param
— targetnya adalah parameter lone
-
Dalam semua konteks lainnya, penyertaan attribute_target_specifier diizinkan tetapi tidak perlu.
Contoh: deklarasi kelas dapat mencakup atau menghilangkan penentu
type
:[type: Author("Brian Kernighan")] class Class1 {} [Author("Dennis Ritchie")] class Class2 {}
contoh akhir.
Implementasi dapat menerima attribute_targetlain, tujuan implementasi yang ditentukan. Implementasi yang tidak mengenali attribute_target tersebut akan mengeluarkan peringatan dan mengabaikan attribute_section yang berisi.
Menurut konvensi, kelas atribut dinamai dengan akhiran Attribute
. Attribute_name dapat menyertakan atau menghilangkan akhiran ini. Secara khusus, attribute_name diselesaikan sebagai berikut:
- Jika pengidentifikasi paling kanan dari attribute_name adalah pengidentifikasi verbatim (§6.4.3), maka attribute_name diselesaikan sebagai type_name (§7,8). Jika hasilnya bukan jenis yang berasal dari
System.Attribute
, kesalahan waktu kompilasi terjadi. - Sebaliknya
-
attribute_name diselesaikan sebagai type_name (§7,8) kecuali kesalahan apa pun ditekan. Jika resolusi ini berhasil dan menghasilkan jenis yang berasal dari
System.Attribute
maka jenisnya adalah hasil dari langkah ini. - Karakter
Attribute
ditambahkan ke pengidentifikasi paling kanan dalam attribute_name dan string token yang dihasilkan diselesaikan sebagai type_name (§7,8) kecuali kesalahan apa pun ditekan. Jika resolusi ini berhasil dan menghasilkan jenis yang berasal dariSystem.Attribute
maka jenisnya adalah hasil dari langkah ini.
-
attribute_name diselesaikan sebagai type_name (§7,8) kecuali kesalahan apa pun ditekan. Jika resolusi ini berhasil dan menghasilkan jenis yang berasal dari
Jika tepat salah satu dari dua langkah di atas menghasilkan jenis yang berasal dari System.Attribute
, maka jenis tersebut adalah hasil dari attribute_name. Jika tidak, kesalahan waktu kompilasi terjadi.
Contoh: Jika kelas atribut ditemukan dengan dan tanpa akhiran ini, ambiguitas ada, dan hasil kesalahan waktu kompilasi. Jika attribute_name dieja sedih sehingga pengidentifikasi paling kanan adalah pengidentifikasi verbatim (§6.4.3), maka hanya atribut tanpa akhiran yang cocok, sehingga memungkinkan ambiguitas seperti itu diselesaikan. Contoh
[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 {}
menunjukkan dua kelas atribut bernama
Example
danExampleAttribute
. Atributnya[Example]
ambigu, karena dapat merujuk keExample
atauExampleAttribute
. Menggunakan pengidentifikasi verbatim memungkinkan niat yang tepat untuk ditentukan dalam kasus langka seperti itu. Atribut[ExampleAttribute]
tidak ambigu (meskipun akan jika ada kelas atribut bernamaExampleAttributeAttribute
!). Jika deklarasi untuk kelasExample
dihapus, kedua atribut merujuk ke kelas atribut bernamaExampleAttribute
, sebagai berikut:[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 {}
contoh akhir
Ini adalah kesalahan waktu kompilasi untuk menggunakan kelas atribut sekali pakai lebih dari sekali pada entitas yang sama.
Contoh: Contoh
[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 {}
menghasilkan kesalahan waktu kompilasi
HelpString
karena mencoba menggunakanClass1
, yang merupakan kelas atribut sekali pakai, lebih dari sekali pada deklarasi .contoh akhir
Ekspresi E
adalah attribute_argument_expression jika semua pernyataan berikut ini benar:
- Jenisnya
E
adalah jenis parameter atribut (§22.2.4). - Pada waktu kompilasi
E
, nilai dapat diatasi ke salah satu hal berikut:
Contoh:
[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; }
contoh akhir
Atribut jenis yang dideklarasikan dalam beberapa bagian ditentukan dengan menggabungkan, dalam urutan yang tidak ditentukan, atribut masing-masing bagiannya. Jika atribut yang sama ditempatkan pada beberapa bagian, atribut tersebut setara dengan menentukan atribut tersebut beberapa kali pada jenisnya.
Contoh: Dua bagian:
[Attr1, Attr2("hello")] partial class A {} [Attr3, Attr2("goodbye")] partial class A {}
setara dengan deklarasi tunggal berikut:
[Attr1, Attr2("hello"), Attr3, Attr2("goodbye")] class A {}
contoh akhir
Atribut pada parameter jenis digabungkan dengan cara yang sama.
22.4 Instans atribut
22.4.1 Umum
Instans atribut adalah instans yang mewakili atribut pada run-time. Atribut didefinisikan dengan kelas atribut, argumen posisi, dan argumen bernama. Instans atribut adalah instans kelas atribut yang diinisialisasi dengan argumen posisi dan bernama.
Pengambilan instans atribut melibatkan pemrosesan waktu kompilasi dan run-time, seperti yang dijelaskan dalam subklasul berikut.
22.4.2 Kompilasi atribut
Kompilasi atribut dengan kelas T
atribut , positional_argument_listP
, , dan ditentukan pada entitas N
program dikompilasi ke dalam rakitan E
melalui langkah-langkah berikut:
- Ikuti langkah-langkah pemrosesan waktu kompilasi untuk mengkompilasi object_creation_expression formulir baru
T(P)
. Langkah-langkah ini mengakibatkan kesalahan waktu kompilasi, atau menentukan konstruktorC
instans padaT
yang dapat dipanggil pada run-time. - Jika
C
tidak memiliki aksesibilitas publik, maka terjadi kesalahan waktu kompilasi. - Untuk setiap named_argument
Arg
diN
:- Biarkan
Name
menjadi pengidentifikasi -
Name
harus mengidentifikasi bidang publik baca-tulis non-statis atau properti padaT
. JikaT
tidak memiliki bidang atau properti seperti itu, maka terjadi kesalahan waktu kompilasi.
- Biarkan
- Jika salah satu nilai dalam positional_argument_list
P
atau salah satu nilai dalam named_argument_listN
berjenisSystem.String
dan nilainya tidak terbentuk dengan baik seperti yang didefinisikan oleh Standar Unicode, nilai yang didefinisikan implementasinya sama dengan nilai run-time yang diambil (§22.4.3).Catatan: Sebagai contoh, string yang berisi unit kode UTF-16 pengganti tinggi yang tidak segera diikuti oleh unit kode pengganti rendah tidak terbentuk dengan baik. catatan akhir
- Simpan informasi berikut (untuk instansiasi run-time atribut) dalam output perakitan oleh pengkompilasi sebagai hasil dari mengkompilasi program yang berisi atribut: kelas
T
atribut , konstruktorC
instans padaT
, ,P
, dan entitasN
program terkait , dengan nilai diselesaikan sepenuhnya pada waktu kompilasi.
22.4.3 Pengambilan run-time instans atribut
Menggunakan istilah yang ditentukan dalam §22.4.2, instans atribut yang diwakili oleh T
, , C
P
, dan N
, dan yang terkait dengan E
dapat diambil pada run-time dari perakitan A
menggunakan langkah-langkah berikut:
- Ikuti langkah-langkah pemrosesan run-time untuk menjalankan object_creation_expression formulir
new T(P)
, menggunakan konstruktorC
instans dan nilai seperti yang ditentukan pada waktu kompilasi. Langkah-langkah ini menghasilkan pengecualian, atau menghasilkan instansO
T
. - Untuk setiap named_argument
Arg
dalamN
, secara berurutan:- Biarkan
Name
menjadi pengidentifikasi JikaName
tidak mengidentifikasi bidang baca-tulis publik atau properti non-statis padaO
, maka pengecualian akan dilemparkan. - Mari kita
Value
jadikan hasil mengevaluasi attribute_argument_expression .Arg
- Jika
Name
mengidentifikasi bidang padaO
, maka atur bidang ini keValue
. - Jika tidak, Nama mengidentifikasi properti pada
O
. Atur properti ini ke Nilai. - Hasilnya adalah
O
, instans kelasT
atribut yang telah diinisialisasi dengan positional_argument_listP
dan named_argument_listN
.
- Biarkan
Catatan: Format untuk menyimpan
T
, ,C
,P
N
(dan mengaitkannya denganE
) diA
dan mekanisme untuk menentukanE
dan mengambilT
, ,C
P
,N
dariA
(dan karenanya bagaimana instans atribut diperoleh pada runtime) berada di luar cakupan spesifikasi ini. catatan akhir
Contoh: Dalam implementasi CLI,
Help
instans atribut dalam rakitan yang dibuat dengan mengkompilasi program contoh di §22.2.3 dapat diambil dengan program berikut: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}"); } } } }
contoh akhir
22.5 Atribut cadangan
22.5.1 Umum
Sejumlah atribut memengaruhi bahasa dalam beberapa cara. Atribut ini meliputi:
-
System.AttributeUsageAttribute
(§22.5.2), yang digunakan untuk menggambarkan cara kelas atribut dapat digunakan. -
System.Diagnostics.ConditionalAttribute
(§22.5.3), adalah kelas atribut multi-penggunaan yang digunakan untuk menentukan metode kondisional dan kelas atribut kondisional. Atribut ini menunjukkan kondisi dengan menguji simbol kompilasi bersyarah. -
System.ObsoleteAttribute
(§22.5.4), yang digunakan untuk menandai anggota sebagai usang. -
System.Runtime.CompilerServices.AsyncMethodBuilderAttribute
(§22.5.5), yang digunakan untuk membuat pembangun tugas untuk metode asinkron. -
System.Runtime.CompilerServices.CallerLineNumberAttribute
(§22.5.6.2),System.Runtime.CompilerServices.CallerFilePathAttribute
(§22.5.6.3), danSystem.Runtime.CompilerServices.CallerMemberNameAttribute
(§22.5.6.4), yang digunakan untuk memberikan informasi tentang konteks panggilan ke parameter opsional.
Atribut analisis statis nullable (§22.5.7) dapat meningkatkan kebenaran peringatan yang dihasilkan untuk nullabilities dan status null (§8.9.5).
Lingkungan eksekusi dapat menyediakan atribut tambahan yang ditentukan implementasi yang memengaruhi eksekusi program C#.
22.5.2 AtributUsage
Atribut AttributeUsage
digunakan untuk menjelaskan cara kelas atribut dapat digunakan.
Kelas yang didekorasi dengan AttributeUsage
atribut harus berasal dari System.Attribute
, baik secara langsung maupun tidak langsung. Jika tidak, terjadi kesalahan waktu kompilasi.
Catatan: Untuk contoh penggunaan atribut ini, lihat §22.2.2. catatan akhir
22.5.3 Atribut Bersyarah
22.5.3.1 Umum
Atribut Conditional
memungkinkan definisi metode kondisional dan kelas atribut kondisional.
22.5.3.2 Metode bersyarah
Metode yang didekorasi dengan Conditional
atribut adalah metode bersyarkat. Setiap metode bersyarat dengan demikian dikaitkan dengan simbol kompilasi bersyarat yang dideklarasikan dalam atributnya Conditional
.
Contoh:
class Eg { [Conditional("ALPHA")] [Conditional("BETA")] public static void M() { // ... } }
menyatakan
Eg.M
sebagai metode bersyarat yang terkait dengan dua simbol kompilasi bersyaratALPHA
danBETA
.contoh akhir
Panggilan ke metode bersyarkat disertakan jika satu atau beberapa simbol kompilasi bersyar terkait didefinisikan pada titik panggilan, jika tidak, panggilan dihilangkan.
Metode bersyukur tunduk pada pembatasan berikut:
- Metode bersyarah harus menjadi metode dalam class_declaration atau struct_declaration. Kesalahan waktu kompilasi terjadi jika
Conditional
atribut ditentukan pada metode dalam deklarasi antarmuka. - Metode bersyarah harus memiliki jenis pengembalian .
void
- Metode kondisional tidak boleh ditandai dengan pengubah
override
. Namun, metode kondisional dapat ditandai dengan pengubahvirtual
. Penimpaan metode tersebut secara implisit kondisional, dan tidak boleh ditandai secara eksplisit denganConditional
atribut . - Metode kondisional tidak boleh menjadi implementasi metode antarmuka. Jika tidak, terjadi kesalahan waktu kompilasi.
- Parameter metode bersyarah tidak boleh berupa parameter output.
Selain itu, kesalahan waktu kompilasi terjadi jika delegasi dibuat dari metode bersyarah.
Contoh: Contoh
#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(); } }
menyatakan sebagai metode bersyarat
Class1.M
.Class2
Metode memanggilTest
metode ini. Karena simbolDEBUG
kompilasi bersyarat didefinisikan, jikaClass2.Test
dipanggil, simbol tersebut akan memanggilM
. Jika simbolDEBUG
belum ditentukan, makaClass2.Test
tidak akan memanggilClass1.M
.contoh akhir
Penting untuk dipahami bahwa penyertaan atau pengecualian panggilan ke metode kondisional dikendalikan oleh simbol kompilasi kondisional pada saat panggilan.
Contoh: Dalam kode berikut
// 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 } }
kelas
Class2
danClass3
masing-masing berisi panggilan ke metodeClass1.F
kondisional , yang bersyukur berdasarkan apakah didefinisikan atau tidakDEBUG
. Karena simbol ini didefinisikan dalam konteksClass2
tetapi tidakClass3
, panggilan keF
dalamClass2
disertakan, sementara panggilan keF
dihilangkanClass3
.contoh akhir
Penggunaan metode kondisional dalam rantai warisan dapat membingungkan. Panggilan yang dilakukan ke metode bersyarah melalui base
, dari formulir base.M
, tunduk pada aturan panggilan metode kondisi normal.
Contoh: Dalam kode berikut
// 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
termasuk panggilan ke yangM
ditentukan di kelas dasarnya. Panggilan ini dihilangkan karena metode dasar bersyukur berdasarkan keberadaan simbolDEBUG
, yang tidak terdefinisi. Dengan demikian, metode menulis ke konsol "Class2.M executed
" saja. Penggunaan pp_declarationyang berdasar dapat menghilangkan masalah tersebut.contoh akhir
22.5.3.3 Kelas atribut kondisional
Kelas atribut (§22.2) yang didekorasi dengan satu atau beberapa Conditional
atribut adalah kelas atribut kondisional. Kelas atribut bersyarat dengan demikian dikaitkan dengan simbol kompilasi bersyarat yang dideklarasikan dalam atributnya Conditional
.
Contoh:
[Conditional("ALPHA")] [Conditional("BETA")] public class TestAttribute : Attribute {}
menyatakan
TestAttribute
sebagai kelas atribut bersyarat yang terkait dengan simbol kompilasi bersyaratALPHA
danBETA
.contoh akhir
Spesifikasi atribut (§22,3) dari atribut bersyarkat disertakan jika satu atau beberapa simbol kompilasi bersyarkat terkait didefinisikan pada titik spesifikasi, jika tidak, spesifikasi atribut dihilangkan.
Penting untuk dicatat bahwa penyertaan atau pengecualian spesifikasi atribut dari kelas atribut bersyarkat dikontrol oleh simbol kompilasi bersyarkat pada titik spesifikasi.
Contoh: Dalam contoh
// 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 {}
kelas
Class1
danClass2
masing-masing didekorasi dengan atributTest
, yang bersyukur berdasarkan apakah ditentukan atau tidakDEBUG
. Karena simbol ini didefinisikan dalam konteksClass1
tetapi tidakClass2
, spesifikasi atribut Uji padaClass1
disertakan, sementara spesifikasiTest
atribut pada dihilangkanClass2
.contoh akhir
22.5.4 Atribut Usang
Atribut Obsolete
digunakan untuk menandai jenis dan anggota jenis yang seharusnya tidak lagi digunakan.
Jika program menggunakan jenis atau anggota yang dihiasi dengan atribut Obsolete
, pengkompilasi akan mengeluarkan peringatan atau kesalahan. Secara khusus, kompilator harus mengeluarkan peringatan jika tidak ada parameter kesalahan yang disediakan, atau jika parameter kesalahan disediakan dan memiliki nilai false
. Kompilator akan mengeluarkan kesalahan jika parameter kesalahan ditentukan dan memiliki nilai true
.
Contoh: Dalam kode berikut
[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(); } }
kelas
A
dihiasi denganObsolete
atribut . Setiap penggunaanA
dalamMain
menghasilkan peringatan yang mencakup pesan yang ditentukan, "Kelas ini usang; gunakan kelasB
sebagai gantinya".contoh akhir
22.5.5 Atribut AsyncMethodBuilder
Atribut ini dijelaskan dalam §15.14.1.
22.5.6 Atribut caller-info
22.5.6.1 Umum
Untuk tujuan seperti pengelogan dan pelaporan, terkadang berguna bagi anggota fungsi untuk mendapatkan informasi waktu kompilasi tertentu tentang kode panggilan. Atribut caller-info menyediakan cara untuk meneruskan informasi tersebut secara transparan.
Ketika parameter opsional diannotasi dengan salah satu atribut caller-info, menghilangkan argumen yang sesuai dalam panggilan tidak selalu menyebabkan nilai parameter default diganti. Sebaliknya, jika informasi yang ditentukan tentang konteks panggilan tersedia, informasi tersebut akan diteruskan sebagai nilai argumen.
Contoh:
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); }
Panggilan ke
Log()
tanpa argumen akan mencetak nomor baris dan jalur file panggilan, serta nama anggota tempat panggilan terjadi.contoh akhir
Atribut caller-info dapat terjadi pada parameter opsional di mana saja, termasuk dalam deklarasi delegasi. Namun, atribut caller-info tertentu memiliki batasan pada jenis parameter yang dapat mereka atribut, sehingga akan selalu ada konversi implisit dari nilai yang diganti ke jenis parameter.
Ini adalah kesalahan untuk memiliki atribut caller-info yang sama pada parameter dari deklarasi mendefinisikan dan menerapkan bagian dari deklarasi metode parsial. Hanya atribut caller-info di bagian yang menentukan yang diterapkan, sedangkan atribut caller-info yang hanya terjadi di bagian penerapan diabaikan.
Informasi penelepon tidak memengaruhi resolusi kelebihan beban. Karena parameter opsional yang dikaitkan masih dihilangkan dari kode sumber pemanggil, resolusi kelebihan beban mengabaikan parameter tersebut dengan cara yang sama mengabaikan parameter opsional lain yang dihilangkan (§12.6.4).
Informasi penelepon hanya diganti ketika fungsi secara eksplisit dipanggil dalam kode sumber. Pemanggilan implisit seperti panggilan konstruktor induk implisit tidak memiliki lokasi sumber dan tidak akan menggantikan informasi pemanggil. Selain itu, panggilan yang terikat secara dinamis tidak akan menggantikan informasi pemanggil. Ketika parameter atribut caller-info dihilangkan dalam kasus seperti itu, nilai default parameter yang ditentukan digunakan sebagai gantinya.
Satu pengecualian adalah ekspresi kueri. Ini dianggap sebagai ekspansi syntactic, dan jika panggilan yang mereka perluas untuk menghilangkan parameter opsional dengan atribut caller-info, informasi penelepon akan diganti. Lokasi yang digunakan adalah lokasi klausa kueri tempat panggilan dihasilkan.
Jika lebih dari satu atribut caller-info ditentukan pada parameter tertentu, atribut tersebut dikenali dalam urutan berikut: CallerLineNumber
, , CallerFilePath
CallerMemberName
. Pertimbangkan deklarasi parameter berikut:
[CallerMemberName, CallerFilePath, CallerLineNumber] object p = ...
CallerLineNumber
lebih diutamakan, dan dua atribut lainnya diabaikan. Jika CallerLineNumber
dihilangkan, CallerFilePath
akan diutamakan, dan CallerMemberName
akan diabaikan. Urutan leksikal atribut ini tidak relevan.
22.5.6.2 Atribut CallerLineNumber
Atribut System.Runtime.CompilerServices.CallerLineNumberAttribute
diizinkan pada parameter opsional ketika ada konversi implisit standar (§10.4.2) dari nilai int.MaxValue
konstanta ke jenis parameter. Ini memastikan bahwa nomor baris non-negatif hingga nilai tersebut dapat diteruskan tanpa kesalahan.
Jika pemanggilan fungsi dari lokasi dalam kode sumber menghilangkan parameter opsional dengan CallerLineNumberAttribute
, maka literal numerik yang mewakili nomor baris lokasi tersebut digunakan sebagai argumen untuk pemanggilan alih-alih nilai parameter default.
Jika pemanggilan mencakup beberapa baris, baris yang dipilih bergantung pada implementasi.
Nomor baris dapat dipengaruhi oleh #line
arahan (§6.5.8).
22.5.6.3 Atribut CallerFilePath
Atribut System.Runtime.CompilerServices.CallerFilePathAttribute
diizinkan pada parameter opsional ketika ada konversi implisit standar (§10.4.2) dari string
ke jenis parameter.
Jika pemanggilan fungsi dari lokasi dalam kode sumber menghilangkan parameter opsional dengan CallerFilePathAttribute
, maka string literal yang mewakili jalur file lokasi tersebut digunakan sebagai argumen untuk pemanggilan alih-alih nilai parameter default.
Format jalur file bergantung pada implementasi.
Jalur file dapat dipengaruhi oleh #line
arahan (§6.5.8).
22.5.6.4 Atribut CallerMemberName
Atribut System.Runtime.CompilerServices.CallerMemberNameAttribute
diizinkan pada parameter opsional ketika ada konversi implisit standar (§10.4.2) dari string
ke jenis parameter.
Jika pemanggilan fungsi dari lokasi dalam isi anggota fungsi atau dalam atribut yang diterapkan ke anggota fungsi itu sendiri atau jenis pengembaliannya, parameter atau parameter jenis dalam kode sumber menghilangkan parameter opsional dengan CallerMemberNameAttribute
, maka string harfiah yang mewakili nama anggota tersebut digunakan sebagai argumen untuk pemanggilan alih-alih nilai parameter default.
Untuk pemanggilan yang terjadi dalam metode generik, hanya nama metode itu sendiri yang digunakan, tanpa daftar parameter jenis.
Untuk pemanggilan yang terjadi dalam implementasi anggota antarmuka eksplisit, hanya nama metode itu sendiri yang digunakan, tanpa kualifikasi antarmuka sebelumnya.
Untuk pemanggilan yang terjadi dalam properti atau aksesor peristiwa, nama anggota yang digunakan adalah properti atau peristiwa itu sendiri.
Untuk pemanggilan yang terjadi dalam pengakses pengindeks, nama anggota yang digunakan adalah yang disediakan oleh IndexerNameAttribute
(§22.6) pada anggota pengindeks, jika ada, atau nama Item
default sebaliknya.
Untuk pemanggilan yang terjadi dalam penginisialisasi bidang atau peristiwa, nama anggota yang digunakan adalah nama bidang atau peristiwa yang sedang diinisialisasi.
Untuk pemanggilan yang terjadi dalam deklarasi konstruktor instans, konstruktor statis, finalizer, dan operator nama anggota yang digunakan bergantung pada implementasi.
22.5.7 Atribut analisis kode
22.5.7.1 Umum
Atribut di bagian ini digunakan untuk memberikan informasi tambahan untuk mendukung pengkompilasi yang menyediakan diagnostik null-state dan null -state (§8.9.5). Pengkompilasi tidak diperlukan untuk melakukan diagnostik status null. Kehadiran atau tidak adanya atribut ini tidak memengaruhi bahasa atau perilaku program. Pengkompilasi yang tidak menyediakan diagnostik status null harus membaca dan mengabaikan keberadaan atribut ini. Pengkompilasi yang menyediakan diagnostik status null harus menggunakan arti yang ditentukan di bagian ini untuk salah satu atribut ini yang digunakannya untuk menginformasikan diagnostiknya.
Atribut analisis kode dideklarasikan dalam namespace System.Diagnostics.CodeAnalysis
.
Atribut | Arti |
---|---|
AllowNull (§22.5.7.2) |
Argumen yang tidak dapat diubah ke null mungkin null. |
DisallowNull (§22.5.7.3) |
Argumen nullable tidak boleh null. |
MaybeNull (§22.5.7.6) |
Nilai pengembalian yang tidak dapat diubah ke null mungkin null. |
NotNull (§22.5.7.8) |
Nilai pengembalian null tidak akan pernah null. |
MaybeNullWhen (§22.5.7.7) |
Argumen yang tidak dapat diubah ke null mungkin null saat metode mengembalikan nilai bool yang ditentukan. |
NotNullWhen (§22.5.7.10) |
Argumen nullable tidak akan null ketika metode mengembalikan nilai yang ditentukan bool . |
NotNullIfNotNull (§22.5.7.9) |
Nilai yang dikembalikan tidak null jika argumen untuk parameter yang ditentukan tidak null. |
DoesNotReturn (§22.5.7.4) |
Metode ini tidak pernah kembali. |
DoesNotReturnIf (§22.5.7.5) |
Metode ini tidak pernah mengembalikan jika parameter terkait bool memiliki nilai yang ditentukan. |
Bagian berikut dalam §22.5.7.1 bersifat normatif kondisional.
22.5.7.2 Atribut AllowNull
Menentukan bahwa nilai null diizinkan sebagai input meskipun jenis yang sesuai melarangnya.
Contoh: Pertimbangkan properti baca/tulis berikut yang tidak pernah ditampilkan
null
karena memiliki nilai default yang wajar. Namun, pengguna dapat memberikan null kepada aksesor yang ditetapkan untuk mengatur properti ke nilai default tersebut.#nullable enable public class X { [AllowNull] public string ScreenName { get => _screenName; set => _screenName = value ?? GenerateRandomScreenName(); } private string _screenName = GenerateRandomScreenName(); private static string GenerateRandomScreenName() => ...; }
Mengingat penggunaan aksesor set properti tersebut berikut
var v = new X(); v.ScreenName = null; // may warn without attribute AllowNull
tanpa atribut, pengompilasi dapat menghasilkan peringatan karena properti bertipe non-nullable tampaknya diatur ke nilai null. Kehadiran atribut menekan peringatan tersebut. contoh akhir
22.5.7.3 Atribut DisallowNull
Menentukan bahwa nilai null tidak diizinkan sebagai input meskipun jenis yang sesuai mengizinkannya.
Contoh: Pertimbangkan properti berikut di mana null adalah nilai default, tetapi klien hanya dapat mengaturnya ke nilai non-null.
#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 accessor dapat mengembalikan nilai default
null
, sehingga pengkompilasi dapat memperingatkan bahwa itu harus diperiksa sebelum akses. Selain itu, ini memperingatkan penelepon bahwa, meskipun bisa null, penelepon tidak boleh secara eksplisit mengaturnya ke null. contoh akhir
22.5.7.4 Atribut DoesNotReturn
Menentukan bahwa metode tertentu tidak pernah kembali.
Contoh: Pertimbangkan hal berikut:
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; }
Kehadiran atribut membantu pengkompilasi dengan sejumlah cara. Pertama, kompilator dapat mengeluarkan peringatan jika ada jalur di mana metode dapat keluar tanpa melemparkan pengecualian. Kedua, kompilator dapat menekan peringatan nullable dalam kode apa pun setelah panggilan ke metode tersebut, sampai klausa tangkapan yang sesuai ditemukan. Ketiga, kode yang tidak dapat dijangkau tidak akan memengaruhi status null apa pun.
Atribut tidak mengubah keterjangkauan (§13.2) atau analisis penetapan pasti (§9,4) berdasarkan keberadaan atribut ini. Ini hanya digunakan untuk memengaruhi peringatan nullability. contoh akhir
22.5.7.5 Atribut DoesNotReturnIf
Menentukan bahwa metode tertentu tidak pernah mengembalikan jika parameter terkait bool
memiliki nilai yang ditentukan.
Contoh: Pertimbangkan hal berikut:
#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!; }
contoh akhir
22.5.7.6 Atribut MaybeNull
Menentukan bahwa nilai pengembalian yang tidak dapat diubah ke null mungkin null.
Contoh: Pertimbangkan metode generik berikut:
#nullable enable public T? Find<T>(IEnumerable<T> sequence, Func<T, bool> predicate) { ... }
Ide dari kode ini adalah bahwa jika
T
digantikan olehstring
,T?
menjadi anotasi nullable. Namun, kode ini tidak legal karenaT
tidak dibatasi untuk menjadi jenis referensi. Namun, menambahkan atribut ini memecahkan masalah:#nullable enable [return: MaybeNull] public T Find<T>(IEnumerable<T> sequence, Func<T, bool> predicate) { ... }
Atribut menginformasikan kepada penelepon bahwa kontrak menyiratkan jenis yang tidak dapat diubah ke null, tetapi nilai pengembalian sebenarnya mungkin
null
. contoh akhir
22.5.7.7 Atribut MaybeNullWhen
Menentukan bahwa argumen yang tidak dapat diubah ke null mungkin null
ketika metode mengembalikan nilai yang ditentukan bool
. Ini mirip MaybeNull
dengan atribut (§22.5.7.6), tetapi menyertakan parameter untuk nilai pengembalian yang ditentukan.
22.5.7.8 Atribut NotNull
Menentukan bahwa nilai nullable tidak akan null
pernah jika metode mengembalikan (bukan melemparkan).
Contoh: Pertimbangkan hal berikut:
#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); }
Ketika jenis referensi null diaktifkan, metode
ThrowWhenNull
dikompilasi tanpa peringatan. Ketika metode itu kembali, argumen dijaminvalue
bukannull
. Namun, dapat diterima untuk memanggilThrowWhenNull
dengan referensi null. contoh akhir
22.5.7.9 Atribut NotNullIfNotNull
Menentukan bahwa nilai pengembalian bukan null
jika argumen untuk parameter yang ditentukan bukan null
.
Contoh: Status null dari nilai pengembalian dapat bergantung pada status null dari satu atau beberapa argumen. Untuk membantu analisis pengkompilasi ketika metode selalu mengembalikan nilai non-null ketika argumen tertentu tidak
null
atributNotNullIfNotNull
dapat digunakan. Pertimbangkan kode berikut:#nullable enable string GetTopLevelDomainFromFullUrl(string url) { ... }
url
Jika argumen tidaknull
,null
tidak dikembalikan. Ketika referensi nullable diaktifkan, tanda tangan tersebut berfungsi dengan benar, asalkan API tidak pernah menerima argumen null. Namun, jika argumen bisa null, maka nilai yang dikembalikan juga bisa null. Untuk mengekspresikan kontrak tersebut dengan benar, anotasi metode ini sebagai berikut:#nullable enable [return: NotNullIfNotNull("url")] string? GetTopLevelDomainFromFullUrl(string? url) { ... }
contoh akhir
22.5.7.10 Atribut NotNullWhen
Menentukan bahwa argumen nullable tidak akan ketika null
metode mengembalikan nilai yang ditentukan bool
.
Contoh: Metode
String.IsNullOrEmpty(String)
pustaka mengembalikantrue
saat argumen adalahnull
atau string kosong. Ini adalah bentuk pemeriksaan null: Penelepon tidak perlu memeriksa argumen null jika metode mengembalikanfalse
. Untuk membuat metode seperti ini sadar nullable, buat jenis parameter sebagai jenis referensi nullable, dan tambahkan atribut NotNullWhen:#nullable enable bool IsNullOrEmpty([NotNullWhen(false)] string? value) { ... }
contoh akhir
22.6 Atribut untuk interoperatur
Untuk interoperatasi dengan bahasa lain, pengindeks dapat diimplementasikan menggunakan properti terindeks. Jika tidak ada IndexerName
atribut yang ada untuk pengindeks, maka nama Item
tersebut digunakan secara default. Atribut ini IndexerName
memungkinkan pengembang untuk mengambil alih default ini dan menentukan nama yang berbeda.
Contoh: Secara default, nama pengindeks adalah
Item
. Ini dapat ditimpa, sebagai berikut:[System.Runtime.CompilerServices.IndexerName("TheItem")] public int this[int index] { get { ... } set { ... } }
Sekarang, nama pengindeks adalah
TheItem
.contoh akhir
ECMA C# draft specification