Зачем C# Caller Info Attributes нужно значение по умолчанию?
Я только что натолкнулся на C# 5 Атрибуты информации о вызывающем абоненте ( http://msdn.microsoft.com/en-us/library/hh534540.aspx).
Это кажется очень полезной функцией, и я прочитал некоторую документацию ( http://www.codeproject.com/Tips/606379/Caller-Info-Attributes-in-Csharp).
Однако мне просто интересно: почему нужно передавать значения по умолчанию? Как они используются?
В следующем примере кода показано, как использовать атрибуты Caller Info:
public static void ShowCallerInfo([CallerMemberName]
string callerName = null, [CallerFilePath] string
callerFilePath = null, [CallerLineNumber] int callerLine=-1)
{
Console.WriteLine("Caller Name: {0}", callerName);
Console.WriteLine("Caller FilePath: {0}", callerFilePath);
Console.WriteLine("Caller Line number: {0}", callerLine);
}
Мой вопрос: каковы значения по умолчанию null
, null
, а также -1
используется для? Чем код выше отличается от:
public static void ShowCallerInfo([CallerMemberName]
string callerName = "hello", [CallerFilePath] string
callerFilePath = "world", [CallerLineNumber] int callerLine=-42)
{
Console.WriteLine("Caller Name: {0}", callerName);
Console.WriteLine("Caller FilePath: {0}", callerFilePath);
Console.WriteLine("Caller Line number: {0}", callerLine);
}
Насколько я понимаю, это необязательные параметры, и компилятор предоставляет значение по умолчанию, заменяя любое значение по умолчанию, которое мы назначаем. В таком случае, почему мы указываем значения по умолчанию? Есть ли какой-то странный крайний случай, когда компилятор не может заполнить значения и прибегает к значениям по умолчанию, которые мы предоставили? Если нет, то почему нас просят ввести эти данные? Кажется довольно неуклюжим попросить разработчиков предоставить значения по умолчанию, которые никогда не будут использоваться.
Отказ от ответственности: я пытался гуглить это, но я не смог ничего найти. Я почти боюсь задавать вопросы по SO, потому что большинство таких вопросов новичка встречается с такой враждебностью, но в крайнем случае я собираюсь рискнуть вопросом. Модераторы / старшие пользователи, без обид - я действительно пытался найти информацию в другом месте, прежде чем публиковать это.
3 ответа
Эти параметры нуждаются в значении по умолчанию, поскольку атрибуты Caller Info были реализованы с использованием необязательных параметров, а необязательные параметры требуют значения по умолчанию. Таким образом, звонок может быть просто ShowCallerInfo()
без необходимости отправлять какие-либо параметры, и компилятор добавит соответствующие.
Почему это было реализовано с использованием необязательных параметров, для начала более глубокий вопрос. Они могли бы сделать это без, и компилятор должен был бы "вставить" эти параметры до начала фактической компиляции, но в отличие от необязательных параметров (что является C# 4.0
особенность) он не будет обратно совместим и сломает другие компиляторы / инструменты анализа кода.
Им нужны значения по умолчанию, чтобы параметры можно было пометить как необязательные. Если вы не укажете параметры при вызове метода, компилятор введет правильные значения для вас, но только если вы их не указали. Если вы это сделаете, то "волшебство" этих атрибутов не произойдет.
Насколько я понимаю, эти атрибуты не влияют на время выполнения и предназначены только для времени компиляции, поэтому значения по умолчанию предназначены только для того, чтобы параметры были необязательными.
Иными словами, в вызываемом объекте (метод, который вызывается, когда атрибут применяется к параметру) параметр должен существовать. С другой стороны, вызывающая сторона должна передать эти аргументы, и единственный способ для компилятора разрешить неопределенный аргумент - дать ему значение по умолчанию.
Хотя атрибуты могут влиять на генерацию кода или выполнение во время выполнения, источник должен быть действительным, если удаляются все атрибуты. Поэтому значение по умолчанию должно быть определено в вызываемом объекте, и компилятор просто генерирует значение аргумента на основе примененного атрибута вместо текущего значения по умолчанию, определенного в вызываемом объекте.
В других ответах упоминается несколько вариантов использования, которые кажутся действительными.
Что-то они упустили, так это то, что они по существу говорят компилятору переписать вызовы этих функций со статическими значениями. Но эти значения не всегда доступны. В этих случаях компилятор не будет перезаписывать вызовы, поэтому будут использоваться значения по умолчанию.
Примеры:
Если вы скомпилируете dll с функцией, которая имеет эти атрибуты, предоставьте ее сценарию, созданному в памяти (скажем, через Roslyn), этот код может не иметь "имени файла".
- Кто-то может возразить, что сгенерированный сценарий должен затем вызывать метод с предоставленными значениями аргументов, но это означает тот же код, который компилятор может компилировать статически (т. Е.
csc mycodefile.cs
) не будет работать с динамической компиляцией во время выполнения даже в том же контексте, что может сбивать с толку.
- Кто-то может возразить, что сгенерированный сценарий должен затем вызывать метод с предоставленными значениями аргументов, но это означает тот же код, который компилятор может компилировать статически (т. Е.
Вы также можете вызвать этот метод через отражение, о котором компилятор просто не знает, чтобы добавить эти значения.
- Среда выполнения /BCL может быть создана, чтобы заставить вызывающую рефлексию предоставлять эти значения, но в любом случае в этом контексте нет никаких значимых значений для имени файла и номера строки.
Вы также можете добавить
[CallerMemberName]
в конструктор атрибута и примените этот атрибут к классу. У этого не будет имени участника.
См. Имена участников в Документах
Конструктор атрибутов
Имя метода или свойства, к которому применяется атрибут. Если атрибутом является любой элемент в члене (например, параметр, возвращаемое значение или параметр универсального типа), то этот результат является именем члена, связанного с этим элементом.
Нет содержащего члена (например, уровня сборки или атрибутов, которые применяются к типам)
Значение по умолчанию необязательного параметра.
Вы также можете указать значения явно, если хотите скрыть информацию о вызывающем абоненте. по какой-то причине. (Может быть, если вы используете обфускацию кода, эти значения могут не измениться, поэтому вы можете указать эти значения в этих случаях, чтобы скрыть вызывающего).
См. Примечания в Документах
Значения информации о вызывающем абоненте передаются как литералы на промежуточном языке (IL) во время компиляции. В отличие от результатов свойства StackTrace для исключений, обфускация не влияет на результаты.
Вы можете явно указать необязательные аргументы для управления информацией о вызывающем абоненте или для скрытия информации о вызывающем абоненте.