Атрибуты сведений о вызывающем коде
В целях ведения журналов и создания отчетов иногда бывает полезно, чтобы функция-член получала определенные сведения о вызывающем коде во время компиляции. Атрибуты сведений о вызывающем коде обеспечивает способ прозрачной передачи такой информации.
Если необязательный параметр аннотирован одним из атрибутов сведений о вызывающем коде, пропуск соответствующего аргумента в вызове не обязательно приводит к замене значения параметра по умолчанию. Напротив, если указанные сведения о вызывающем контексте доступны, они передаются в качестве значения аргумента.
Пример:
using System.Runtime.CompilerServices
…
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);
}
Вызов метода Log() без аргументов приведет к печати номера строки пути к файлу для вызова, а также имени члена, в котором этот вызов выполняется.
Атрибуты сведений о вызывающем коде могут содержаться в необязательных параметрах в любом месте программы, в том числе в объявлениях делегатов. Однако конкретные атрибуты сведений о вызывающем коде имеют ограничения, касающиеся типов параметров, к которым они могут применяться. Поэтому всегда выполняется неявное преобразование из типа подставляемого значения в тип параметра.
Применение одного атрибута сведений о вызывающем коде к параметру, содержащемуся одновременно в определяющей и реализующей частях объявления разделяемого метода, приводит к ошибке. Применяются только атрибуты сведений о вызывающем коде в определяющем объявлении, тогда как атрибуты сведений о вызывающем коде из реализующего объявления пропускаются.
Сведения о вызывающем коде не влияют на разрешение перегрузок. Если необязательные параметры с атрибутами отсутствуют в исходном вызывающем коде, эти параметры пропускаются при разрешении перегрузок точно так же, как пропускаются все другие отсутствующие необязательные параметры (§7.5.3).
Сведения о вызывающем коде подставляются только при явном вызове функции в исходном коде. Неявные вызовы, такие как неявные вызовы родительского конструктора, не имеют исходного местоположения и не приводят к подстановке сведений о вызывающем коде. Динамически привязанные вызовы также не подставляют сведения о вызывающем коде. Если в таких вызовах не указывается параметр с атрибутом сведений о вызывающем коде, вместо него используется заданное значение параметра по умолчанию.
Единственным исключением являются выражения запросов. Они считаются синтаксическими расширениями, и, если в расширяемых ими вызовах отсутствуют параметры с атрибутами сведений о вызывающем коде, сведения о вызывающем коде подставляются. В качестве местоположения используется местоположение предложения запроса, из которого был создан вызов.
Если для параметра указано несколько атрибутов сведений о вызывающем коде, они используются в следующем порядке: CallerLineNumber, CallerFilePath, CallerMemberName.
Атрибут CallerLineNumber
Атрибут System.Runtime.CompilerServices.CallerLineNumberAttribute разрешается применять к необязательным параметрам при наличии стандартного неявного преобразования (§6.3.1) из константного значения int.MaxValue в тип параметра. Это обеспечивает отсутствие ошибок при передаче любых неотрицательных номеров строк в это значение.
Если при вызове функции из некоторого местоположения в исходном коде не указывается необязательный параметр с атрибутом CallerLineNumberAttribute, то вместо значения параметра по умолчанию в качестве аргумента вызова используется числовой литерал, представляющий номер строки данного местоположения.
Если вызов распространяется на несколько строк, выбор строки зависит от конкретной реализации.
Обратите внимание, что на значение номера строки могут влиять директивы #line (§2.5.7).
Атрибут CallerFilePath
Атрибут System.Runtime.CompilerServices.CallerFilePathAttribute разрешается применять к необязательным параметрам при наличии стандартного неявного преобразования (§6.3.1) из типа string в тип параметра.
Если при вызове функции из некоторого местоположения в исходном коде не указывается необязательный параметр с атрибутом CallerFilePathAttribute, то вместо значения параметра по умолчанию в качестве аргумента вызова используется строковый литерал, представляющий путь к файлу для данного местоположения.
Формат пути к файлу зависит от реализации.
Обратите внимание, что на значение пути к файлу могут влиять директивы #line (§2.5.7).
Атрибут CallerMemberName
Атрибут System.Runtime.CompilerServices.CallerMemberNameAttribute разрешается применять к необязательным параметрам при наличии стандартного неявного преобразования (§6.3.1) из типа string в тип параметра.
Если при вызове функции из некоторого местоположения внутри тела функции-члена или внутри атрибута, применяемого к самой функции-члену или ее типу возвращаемого значения, в составе параметров или параметров типов исходного кода отсутствует необязательный параметр с атрибутом CallerMemberNameAttribute, то вместо значения параметра по умолчанию в качестве аргумента вызова используется строковый литерал, представляющий имя этого члена.
Для вызовов, осуществляемых из универсальных методов, используется только имя самого метода без списка параметров типов.
Для вызовов из явных реализаций членов интерфейса используется только имя самого метода без предшествующего имени интерфейса.
Для вызовов из методов доступа к свойствам или событиям в качестве имени члена используется имя самого свойства или события.
Для вызовов из методов доступа к индексатору в качестве имени члена используется имя, предоставляемое атрибутом IndexerNameAttribute (§17.5.2.1), или имя члена индексатора (при его наличии); в противном случае используется имя Item по умолчанию.
Для вызовов, осуществляемых из объявлений конструкторов экземпляров, использование имени члена статических конструкторов, деструкторов или операторов зависит от конкретной реализации.
Атрибуты для взаимодействия
Примечание. Этот раздел применим только для реализации Microsoft .NET языка C#.