Обновление. Это больше не проблема с С# 6, которая внедрила оператор
nameofдля решения таких сценариев (см. MSDN).Примечание. Обратитесь к разделу Получение имен локальных переменных (и параметров) во время выполнения через лямбда-выражения" для обобщения этот вопрос, а также некоторые ответы.
Мне нравится идея использования лямбда-выражений для создания рефакторизуемых реализаций интерфейса INotifyPropertyChanged, используя код, аналогичный тому, который предоставляется Eric De Carufel.
Im экспериментирует с реализацией чего-то подобного для предоставления имени параметра ArgumentException (или его производных классов) в режиме рефакторинга.
Я определил следующий метод утилиты для выполнения проверок null:
public static void CheckNotNull<T>(Expression<Func<T>> parameterAccessExpression)
{
    Func<T> parameterAccess = parameterAccessExpression.Compile();
    T parameterValue = parameterAccess();
    CheckNotNull(parameterValue, parameterAccessExpression);
}
public static void CheckNotNull<T>(T parameterValue, 
    Expression<Func<T>> parameterAccessExpression)
{
    if (parameterValue == null)
    {
        Expression bodyExpression = parameterAccessExpression.Body;
        MemberExpression memberExpression = bodyExpression as MemberExpression;
        string parameterName = memberExpression.Member.Name;
        throw new ArgumentNullException(parameterName);
    }
}
Проверка правильности аргумента может быть выполнена в режиме рефакторинга с использованием следующего синтаксиса:
CheckNotNull(() => arg);           // most concise
CheckNotNull(arg, () => args);     // equivalent, but more efficient
Моя забота заключается в следующих строках:
Expression bodyExpression = parameterAccessExpression.Body;
MemberExpression memberExpression = bodyExpression as MemberExpression;
A MemberExpression представляет "доступ к полю или свойству". Он гарантированно работает корректно в случае INotifyPropertyChanged, поскольку выражение лямбда будет доступностью свойств.
Однако в моем коде выше выражение лямбда семантически относится к параметру, а не к доступу к полю или свойствам. Единственная причина, по которой работает код, заключается в том, что компилятор С# продвигает любые локальные переменные (и параметры), которые фиксируются в анонимных функциях для переменных экземпляра в классе, создаваемом компилятором, за кулисами. Это подтверждается Jon Skeet.
Мой вопрос: Является ли это поведение (продвижение захваченных параметров в переменные экземпляра) документированным в спецификации .NET, или это просто деталь реализации, которая может измениться в альтернативных реализациях или будущих версиях структуры? В частности, могут быть среды, в которых parameterAccessExpression.Body is MemberExpression возвращает false?
