Перечисления в лямбда-выражениях компилируются по-разному; следствие улучшения разрешения перегрузки?

При испытании Visual Studio 2015 RC я получил ошибку времени выполнения в ранее работавшем коде. Учитывая лямбду (x => x.CustomerStatusID == CustomerStatuses.Active), которая была передана функции как Expression<>, отладчик показывает разницу в дереве выражений. Раньше он компилировался так:

.Lambda #Lambda1<System.Func`2[Services.DataClasses.CustomerDC,System.Boolean]>(Services.DataClasses.CustomerDC $x)
{
    (System.Int32)$x.CustomerStatusID == 0
}

Но в C# 6.0 теперь он компилируется как

.Lambda #Lambda1<System.Func`2[Services.DataClasses.CustomerDC,System.Boolean]>(Services.DataClasses.CustomerDC $x)
{
    (System.Int32)$x.CustomerStatusID == (System.Int32).Constant<Services.DataClasses.CustomerStatuses>(Active)
}

Хотя исправление моего кода обхода дерева было простым, и дополнительные детали приветствуются, кто-нибудь знает о каких-либо других подводных камнях, подобных этой?

В качестве альтернативы, есть ли у кого-нибудь ссылка на информацию о том, как было улучшено разрешение перегрузки? Я не могу найти.


person Ron Newcomb    schedule 29.05.2015    source источник
comment
Каковы были тип исключения времени выполнения и сообщение?   -  person Erik Philips    schedule 30.05.2015
comment
@ErikPhilips Нет никаких исключений. Проще говоря, до (‹= 4.5) компилятор строил бы выражение типа Expression.Constant(0) (то есть int), а с Roslyn более корректно строит выражение типа Expression.Constant(CustomerStatuses.Active), то есть используя перечисление с его значением. Технически он строит выражение вроде Expression.Convert(Expression.Constant(CustomerStatuses.Active), typeof(int)). Учитывая, что 0 специально обрабатывается как значение перечисления, я протестировал его с 1. Тот же результат.   -  person xanatos    schedule 30.05.2015
comment
Вы должны обновить свой вопрос, ваше первое предложение гласит I received a run-time error on previously working code.   -  person Erik Philips    schedule 30.05.2015
comment
Результат онлайн-трирослина, где его можно увидеть: goo.gl/a2vmaS   -  person xanatos    schedule 30.05.2015
comment
Это проблема только с нулевым значением перечисления, верно? Я подозреваю, что это связано с тем, что компилятор выполняет какую-то оптимизацию со значением по умолчанию, чего действительно не следовало делать для деревьев выражений, и это считалось ошибкой.   -  person Mike Zboray    schedule 30.05.2015
comment
@xanatos Я тестировал его с 1. Тот же результат. Вы имеете в виду, что между компиляторами нет разницы или такая же разница существует?   -  person Mike Zboray    schedule 30.05.2015
comment
@mikez Нет ... Что обработка 0 и обработка 1 одинакова, поэтому отличается между C # 5.0 и 6.0 (по крайней мере, на трирослине)   -  person xanatos    schedule 30.05.2015
comment
@xanatos Да, я вижу это сейчас. На самом деле вы можете просто запустить ToString на обоих и увидеть, что вывод отличается (.NET 4.5 против Рослин). Я все еще думаю, что это, вероятно, изменилось, потому что это считалось ошибкой, но я ничего не вижу в репозитории roslyn или подключаюсь с первого взгляда.   -  person Mike Zboray    schedule 30.05.2015
comment
Ксанатос правильно. Без нашей практики защитного кодирования мы могли бы в конечном итоге получить обычный NullRef или, что еще хуже, молча неправильные результаты. Меня беспокоит то, что я не могу найти никакой литературы об этом изменении C# 6.0, потому что новый синтаксический сахар и добавление функций привлекают внимание. Все, что я когда-либо видел в изменении перегрузки, - это расплывчатое упоминание о nullables, но без примеров. Поэтому и спрашиваю у сообщества.   -  person Ron Newcomb    schedule 30.05.2015
comment
@RonNewcomb Это, безусловно, критическое изменение ... И он добавляет третий способ записи сравнения с перечислением: (int)property == num, (int)property == (int)enumValue, property == enumValue (третий - это тот, который вы обычно пишете, если пишете дерево выражений вручную )   -  person xanatos    schedule 30.05.2015
comment
Вы должны опубликовать/спросить об этом на github.com/dotnet/roslyn/issues, если у вас нет уже нет.   -  person JoshVarty    schedule 31.05.2015
comment
IIRC, точный способ преобразования выражений в деревья выражений намеренно занижен. Результатом этого является то, что вы можете легко получить различия между разными компиляторами. Однако у меня нет какой-либо документации или других справок об этом. Во всяком случае, это не связано с разрешением перегрузки.   -  person    schedule 17.06.2015
comment
В этой статье есть много объяснений о С# 6 двусмысленности" rel="nofollow noreferrer">blog.slaks.net/2014-05-28/   -  person leat    schedule 22.06.2015
comment
Не уверен, что это та же проблема, так как вы не публикуете подробности ошибки, но в моем случае тип данных не соответствует моему db. У меня есть тип перечисления как small int, и это вызывало проблему при преобразовании в перечисление, которое я меняю те, которые помещаются в базу данных, и работает, опять же, не уверен, что проблема такая же, поскольку вы не указываете информацию об ошибке   -  person Son_of_Sam    schedule 23.06.2015


Ответы (1)


Это не имеет ничего общего с разрешением перегрузки. Предыдущий компилятор преждевременно оптимизировал правую часть сравнения, тем самым опуская код, соответствующий исходному выражению.

person Neal Gafter    schedule 23.06.2015