Я наткнулся на код, который сказал
public int MaxHealth =>
Memory[Address].IsValid ?
Memory[Address].Read<int>(Offs.Life.MaxHp) :
0;
Теперь я немного знаком с лямбда-выражениями. Я просто не видел, чтобы он использовал это таким образом.
Какая разница между приведенным выше заявлением и
public int MaxHealth = x ? y:z;
Ответы:
То, на что вы смотрите, это член с выражением тела, а не лямбда-выражение.
Когда компилятор встречает элемент свойства с выражением-выражением , он по сути преобразует его в метод получения, подобный этому:
(Вы можете убедиться в этом сами, накачав код в инструмент под названием TryRoslyn .)
Члены с выраженным выражением - как и большинство функций C # 6 - просто синтаксический сахар . Это означает, что они не предоставляют функциональность, которая не могла бы быть достигнута с помощью существующих функций. Вместо этого эти новые функции позволяют использовать более выразительный и лаконичный синтаксис
Как вы можете видеть, члены с выражением выражения имеют несколько горячих клавиш, которые делают элементы свойств более компактными:
return
оператор, потому что компилятор может сделать вывод, что вы хотите вернуть результат выраженияget
ключевое слово, поскольку оно подразумевается использованием синтаксиса члена-выражения-тела.Я выделил последний пункт жирным шрифтом, потому что он имеет отношение к вашему актуальному вопросу, на который я сейчас отвечу.
Разница между...
И...
Это так же, как разница между ...
И...
Который - если вы понимаете свойства - должен быть очевидным.
Просто для ясности: первый список - это свойство с геттером под капотом, которое будет вызываться при каждом обращении к нему. Второй листинг - это поле с инициализатором поля, выражение которого вычисляется только один раз, когда создается экземпляр типа.
Это различие в синтаксисе на самом деле довольно тонкое и может привести к «погрешности», описанной Биллом Вагнером в посте «AC # 6 gotcha: Инициализация против членов тела с выражением» .
Хотя члены с выражением тела похожи на лямбда-выражения , они не являются лямбда-выражениями. Принципиальное отличие состоит в том, что лямбда-выражение приводит либо к экземпляру делегата, либо к дереву выражений. Элементы с выражением в выражении - это просто директива для компилятора для создания свойства за сценой. Сходство (более или менее) начинается и заканчивается стрелкой (
=>
).Я также добавлю, что члены с выраженным выражением не ограничены членами собственности. Они работают на всех этих членов:
Добавлено в C # 7.0
Тем не менее, они не работают над этими членами:
источник
Хорошо ... Я сделал комментарий, что они разные, но не могу точно объяснить, как, но теперь я знаю.
это не то же самое, что
Вот разница ...
Когда вы используете автоинициализатор, свойство создает экземпляр значения и использует это значение постоянно. В вышеприведенном посте есть неработающая ссылка на Билла Вагнера, которая хорошо это объясняет, и я искал правильную ссылку, чтобы понять ее сам.
В моей ситуации у меня было свойство автоматически инициализировать команду в ViewModel для View. Я изменил свойство, чтобы использовать инициализатор с выражением bodied, и команда CanExecute перестала работать.
Вот как это выглядело, и вот что происходило.
вот что я изменил.
Разница здесь в том, что когда я использую,
{ get; } =
я создаю и ссылаюсь на ту же команду в этом свойстве. Когда я использую,=>
я фактически создаю новую команду и возвращаю ее каждый раз, когда вызывается свойство. Поэтому я никогда не мог обновитьCanExecute
свою команду, потому что я всегда говорил ей обновить новую ссылку на эту команду.Все это говорит, что если вы просто указываете на вспомогательное поле, то это работает нормально. Это происходит только тогда, когда тело auto или expression создает возвращаемое значение.
источник
Это новая функция C # 6, называемая членом с выражением, которая позволяет вам определять свойство только для получения, используя лямбда-подобную функцию.
Хотя это считается синтаксическим сахаром для следующего, они могут не производить идентичный IL:
Оказывается, что если вы скомпилируете обе версии выше и сравните сгенерированный IL для каждой, вы увидите, что они почти одинаковы.
Вот IL для классической версии в этом ответе, когда она определена в классе с именем
TestClass
:И вот IL для версии члена в теле выражения, когда он определен в классе с именем
TestClass
:См. Https://msdn.microsoft.com/en-us/magazine/dn802602.aspx для получения дополнительной информации об этой и других новых функциях в C # 6.
См. Этот пост Разница между свойством и полем в C # 3.0+ о разнице между полем и средством получения свойства в C #.
Обновить:
Обратите внимание, что члены с выражением тела были расширены, чтобы включить свойства, конструкторы, финализаторы и индексаторы в C # 7.0.
источник
Он называется Expression Bodied Member и был введен в C # 6. Это просто синтаксический сахар над
get
единственным свойством.Это эквивалентно:
Доступен эквивалент объявления метода:
Главным образом позволяя вам сократить шаблон.
источник
Еще один важный момент, если вы используете C # 6:
'=>' может использоваться вместо 'get' и используется только для методов 'get only' - его нельзя использовать с 'set'.
Для C # 7 см. Комментарий от @avenmore ниже - теперь его можно использовать в других местах. Вот хорошая ссылка - https://csharp.christiannagel.com/2017/01/25/expressionbodiedmembers/
источник
За следующее утверждение поделился Алекс Букер в своем ответе
Пожалуйста, смотрите следующий скриншот , он показывает, как это утверждение (используя ссылку SharpLab )
превращается в
Скриншот:
источник