Поделиться через


Определение сведений вызывающего объекта с помощью атрибутов, интерпретируемых компилятором C#

Используя атрибуты сведений, вы получаете сведения о вызывающем методе. Вы получите путь к файлу исходного кода, номер строки в исходном коде и имя участника вызывающего объекта. Чтобы получить сведения о вызывающем элементе, используйте атрибуты, применяемые к необязательным параметрам. Каждый необязательный параметр задает значение по умолчанию. В следующей таблице перечислены атрибуты сведений о вызывающем объекте, определенные в пространстве имен 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 аргумент. Когда разработчик вызывает Operationnull аргумент, в следующем сообщении хранится следующее сообщение:ArgumentException

Argument failed validation: <func is not null>

Этот атрибут позволяет создавать служебные программы диагностики, предоставляющие дополнительные сведения. Разработчики могут быстрее понять, какие изменения необходимы. Можно также использовать для CallerArgumentExpressionAttribute определения того, какое выражение использовалось в качестве приемника для методов расширения. В следующем методе последовательность выполняется через регулярные интервалы. Если последовательность содержит меньше элементов, чем частота, она сообщает об ошибке:

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;
    }
}

В предыдущем примере для параметра sequenceиспользуется nameof оператор. Эта функция доступна в C# 11. Перед C# 11 необходимо ввести имя параметра в виде строки. Этот метод можно вызвать следующим образом:

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

В предыдущем примере создается сообщение, сообщение которого является следующим текстом ArgumentException :

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

См. также