Bagikan melalui


Tentukan informasi pemanggil menggunakan atribut yang ditafsirkan oleh kompilator C#

Dengan menggunakan atribut info, Anda mendapatkan informasi tentang pemanggil ke sebuah metode. Anda mendapatkan jalur file kode sumber, nomor baris dalam kode sumber, dan nama anggota pemanggil. Untuk mendapatkan informasi pemanggil anggota, Anda menggunakan atribut yang diterapkan ke parameter opsional. Setiap parameter opsional menentukan nilai default. Tabel berikut mencantumkan atribut Info Pemanggil yang ditentukan di namespace layanan System.Runtime.CompilerServices:

Atribut Deskripsi Jenis
CallerFilePathAttribute Jalur lengkap file sumber yang berisi pemanggil. Jalur lengkap adalah jalur pada waktu kompilasi. String
CallerLineNumberAttribute Nomor baris dalam file sumber tempat metode dipanggil. Integer
CallerMemberNameAttribute Nama metode atau nama properti pemanggil. String
CallerArgumentExpressionAttribute Representasi string dari ekspresi argumen. String

Informasi ini membantu Anda dengan pelacakan dan debugging, dan membantu Anda untuk membuat alat diagnostik. Contoh berikut menunjukkan cara menggunakan atribut info pemanggil. Pada setiap panggilan ke metode TraceMessage, informasi pemanggil dimasukkan untuk argumen ke parameter opsional.

public void DoProcessing()
{
    TraceMessage("Something happened.");
}

public void TraceMessage(string message,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string sourceFilePath = "",
        [CallerLineNumber] int sourceLineNumber = 0)
{
    Trace.WriteLine("message: " + message);
    Trace.WriteLine("member name: " + memberName);
    Trace.WriteLine("source file path: " + sourceFilePath);
    Trace.WriteLine("source line number: " + sourceLineNumber);
}

// Sample Output:
//  message: Something happened.
//  member name: DoProcessing
//  source file path: c:\Visual Studio Projects\CallerInfoCS\CallerInfoCS\Form1.cs
//  source line number: 31

Anda menentukan nilai default eksplisit untuk setiap parameter opsional. Anda tidak dapat menerapkan atribut info penelepon ke parameter yang tidak ditentukan sebagai opsional. Atribut info penelepon tidak menjadikan parameter bersifat opsional. Sebaliknya, atribut tersebut memengaruhi nilai default yang diteruskan saat argumen dihilangkan. Nilai info pemanggil dipancarkan sebagai literal ke Bahasa Perantara (IL) pada waktu kompilasi. Berbeda dengan hasil properti StackTrace untuk pengecualian, hasilnya tidak terpengaruh oleh kebingungan. Anda dapat secara eksplisit memberikan argumen opsional untuk mengontrol informasi pemanggil atau untuk menyembunyikan informasi pemanggil.

Nama anggota

Anda dapat menggunakan atribut CallerMemberName untuk menghindari penentuan nama anggota sebagai argumen String untuk metode yang dipanggil. Dengan menggunakan teknik ini, Anda menghindari masalah bahwa Mengganti Nama Refaktoring tidak akan mengubah nilai String. Keuntungan ini sangat berguna untuk tugas-tugas berikut:

  • Menggunakan rutinitas pelacakan dan diagnostik.
  • Menerapkan antarmuka INotifyPropertyChanged saat mengikat data. Antarmuka ini memungkinkan properti objek untuk memberi tahu kontrol terikat bahwa properti telah berubah. Kontrol dapat menampilkan informasi yang diperbarui. Tanpa atribut CallerMemberName, Anda harus menentukan nama properti sebagai harfiah.

Bagan berikut menunjukkan nama anggota yang dikembalikan saat Anda menggunakan atribut CallerMemberName.

Panggilan dilakukan dalam Hasil nama anggota
Metode, properti, atau peristiwa Nama metode, properti, atau peristiwa asal panggilan.
Konstruktor String ".ctor"
Konstruktor statis String ".cctor"
Finalizer String "Finalize"
Operator atau konversi yang ditentukan pengguna Nama yang dibuat untuk anggota, misalnya, "op_Addition".
Konstruktor atribut Nama metode atau properti di mana atribut diterapkan. Jika atributnya adalah elemen apa pun di dalam anggota (seperti parameter, nilai pengembalian, atau parameter berjenis generik), hasil ini adalah nama anggota yang terkait dengan elemen itu.
Tida berisi anggota (misalnya, tingkat rakitan atau atribut yang diterapkan ke jenis) Nilai default parameter opsional.

Ekspresi argumen

Anda menggunakan System.Runtime.CompilerServices.CallerArgumentExpressionAttribute saat Anda ingin ekspresi diteruskan sebagai argumen. Pustaka diagnostik mungkin ingin memberikan detail selengkapnya tentang ekspresi yang diteruskan ke argumen. Dengan memberikan ekspresi yang memicu diagnostik, selain nama parameter, pengembang memiliki detail lebih lanjut tentang kondisi yang memicu diagnostik. Informasi tambahan tersebut memudahkan untuk perbaikan.

Contoh berikut menunjukkan bagaimana Anda bisa memberikan informasi mendetail tentang argumen saat itu tidak valid:

public static void ValidateArgument(string parameterName, bool condition, [CallerArgumentExpression("condition")] string? message=null)
{
    if (!condition)
    {
        throw new ArgumentException($"Argument failed validation: <{message}>", parameterName);
    }
}

Anda akan memanggilnya seperti yang ditunjukkan pada contoh berikut:

public void Operation(Action func)
{
    Utilities.ValidateArgument(nameof(func), func is not null);
    func();
}

Ekspresi yang digunakan untuk condition disuntikkan oleh kompilator ke dalam argumen message. Saat pengembang memanggil Operation dengan argumen null, pesan berikut disimpan di ArgumentException:

Argument failed validation: <func is not null>

Dengan atribut ini, Anda dapatmenulis utilitas diagnostik yang memberikan detail lebih lanjut. Pengembang dapat lebih cepat memahami perubahan apa yang diperlukan. Anda juga dapat menggunakan CallerArgumentExpressionAttribute untuk menentukan ekspresi apa yang digunakan sebagai penerima untuk metode ekstensi. Metode berikut mengambil sampel urutan secara berkala. Jika urutan memiliki elemen lebih sedikit daripada frekuensi, ini melaporkan kesalahan:

public static IEnumerable<T> Sample<T>(this IEnumerable<T> sequence, int frequency, 
    [CallerArgumentExpression(nameof(sequence))] string? message = null)
{
    if (sequence.Count() < frequency)
        throw new ArgumentException($"Expression doesn't have enough elements: {message}", nameof(sequence));
    int i = 0;
    foreach (T item in sequence)
    {
        if (i++ % frequency == 0)
            yield return item;
    }
}

Contoh sebelumnya menggunakan operator nameof untuk parameter sequence. Fitur tersebut tersedia di C# 11. Sebelum C# 11, Anda harus mengetikkan nama parameter sebagai string. Anda dapat memanggil metode ini sebagai berikut:

sample = Enumerable.Range(0, 10).Sample(100);

Contoh sebelumnya akan melemparkan pesan ArgumentException, pesannya adalah teks berikut:

Expression doesn't have enough elements: Enumerable.Range(0, 10) (Parameter 'sequence')

Lihat juga