使用資訊屬性時,您會取得方法呼叫者的相關信息。 您可以取得原始碼的檔案路徑、原始程式碼中的行號,以及呼叫者的成員名稱。 若要取得成員呼叫端資訊,您可以使用套用至選擇性參數的屬性。 每個選擇性參數都會指定預設值。 下表列出命名空間中 System.Runtime.CompilerServices 定義的呼叫端資訊屬性:
| 屬性 | 說明 | 類型 |
|---|---|---|
| CallerFilePathAttribute | 包含呼叫端之原始程序檔的完整路徑。 完整路徑是在編譯時期的路徑。 | String |
| CallerLineNumberAttribute | 在來源檔案中呼叫方法的行號。 | Integer |
| CallerMemberNameAttribute | 呼叫者的方法名稱或屬性名稱。 | String |
| CallerArgumentExpressionAttribute | 自變數表達式的字串表示。 | String |
此資訊可協助您進行追蹤和偵錯,並協助您建立診斷工具。 下列範例示範如何使用呼叫端資訊屬性。 在方法的每個呼叫 TraceMessage 上,都會將自變數的呼叫端資訊插入至選擇性參數。
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
您可以為每個選擇性參數指定明確的預設值。 您無法將呼叫端資訊屬性套用至未指定為選擇性的參數。 呼叫端資訊屬性不會讓參數成為選擇性。 相反地,它們會影響當參數被省略時傳入的預設值。 呼叫端資訊值會在編譯時期發出為中繼語言 (IL) 的常值。 與例外屬性的結果 StackTrace 不同,混淆不會影響結果。 您可以明確提供選擇性自變數來控制呼叫端資訊,或隱藏呼叫端資訊。
成員名稱
您可以使用 CallerMemberName 屬性來避免將成員名稱指定為 String 所呼叫方法的自變數。 藉由使用這項技術,您可以避免 重新命名重構 不會變更 String 值的問題。 這項優點特別適用於下列工作:
- 使用追蹤和診斷程序。
- 在綁定數據時實作INotifyPropertyChanged介面。 此介面允許物件的屬性通知綁定控制項該屬性變更。 控制件可以顯示更新的資訊。 若沒有
CallerMemberName屬性,您必須將屬性名稱指定為字面值。
下圖顯示當您使用 CallerMemberName 屬性時所傳回的成員名稱。
| 呼叫會發生在 內 | 成員名稱結果 |
|---|---|
| 方法、屬性或事件 | 呼叫的來源方法、屬性或事件名稱。 |
| 建構函式 | 字串 “.ctor” |
| 靜態建構函式 | 字串 “.cctor” |
| 終結器 | 字串「完成」 |
| 使用者定義的運算子或轉換 | 成員生成的名稱,例如「op_Addition」。 |
| 屬性建構函式 | 套用屬性之方法或屬性的名稱。 如果屬性是成員內的任何元素(例如參數、回傳值或一般型別參數),這個結果就是該元素所關聯的成員名稱。 |
| 不包含成員(例如,套用至型別的元件層級或屬性) | 選擇性參數的預設值。 |
自變數表達式
當您要將表示式當做自變數傳遞時,請使用 System.Runtime.CompilerServices.CallerArgumentExpressionAttribute 。 診斷函式庫可以提供更多關於傳遞給參數的 表達 式細節。 除了參數名稱之外,藉由提供觸發診斷的表達式,開發人員還有觸發診斷之條件的詳細數據。 該額外資訊可讓您更輕鬆地修正。
下列範例示範如何在自變數無效時提供自變數的詳細資訊:
public static void ValidateArgument(string parameterName, bool condition, [CallerArgumentExpression("condition")] string? message=null)
{
if (!condition)
{
throw new ArgumentException($"Argument failed validation: <{message}>", parameterName);
}
}
您會叫用它,如下列範例所示:
public void Operation(Action func)
{
Utilities.ValidateArgument(nameof(func), func is not null);
func();
}
編譯器會將所用 condition 的表達式注入參數中 message 。 當開發人員使用 Operation 自變數呼叫 null 時,下列訊息會儲存在 中ArgumentException:
Argument failed validation: <func is not null>
這個屬性可讓您撰寫提供更多詳細數據的診斷公用程式。 開發人員可以更快速地瞭解需要哪些變更。 你也可以用 CallerArgumentExpressionAttribute 來判斷擴展成員接收器使用的表達式。 下列方法會定期取樣序列。 如果序列的元素少於頻率,則會報告錯誤:
extension<T>(IEnumerable<T> sequence)
{
public IEnumerable<T> Sample(int frequency,
[CallerArgumentExpression(nameof(sequence))] string? message = null)
{
if (sequence.Count() < frequency)
throw new InvalidOperationException($"Expression doesn't have enough elements: {message}");
int i = 0;
foreach (T item in sequence)
{
if (i++ % frequency == 0)
yield return item;
}
}
}
上述範例使用 nameof 參數 sequence的運算符。 您可以呼叫此方法,如下所示:
sample = Enumerable.Range(0, 10).Sample(100);
上述範例會擲回 ArgumentException 其訊息為下列文字的 :
Expression doesn't have enough elements: Enumerable.Range(0, 10) (Parameter 'sequence')