Енумите в ламбда изразите се компилират по различен начин; следствие от подобренията на разделителната способност на претоварване?

Докато изпробвах 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), така че използвайки enum с неговата стойност. Технически той изгражда израз като Expression.Convert(Expression.Constant(CustomerStatuses.Active), typeof(int)). Като се има предвид, че 0 се обработва специално като стойност enum, тествах го с 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
Резултат от онлайн tryroslyn, където може да се види: goo.gl/a2vmaS   -  person xanatos    schedule 30.05.2015
comment
Това е само проблем с 0 стойност на enum, нали? Подозирам, че това е свързано с това, че компилаторът прави някаква оптимизация със стойността по подразбиране, което наистина не трябваше да прави за изразни дървета и се смяташе за грешка.   -  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 (поне на tryroslyn)   -  person xanatos    schedule 30.05.2015
comment
@xanatos Да, сега го виждам. Всъщност можете просто да стартирате ToString и на двете и да видите, че изходът е различен (.NET 4.5 срещу Рослин). Все още мисля, че вероятно се е променило, защото се смяташе за грешка, но не виждам нищо в roslyn repo или връзка на пръв поглед.   -  person Mike Zboray    schedule 30.05.2015
comment
xanatos е прав. Без нашите защитни практики за кодиране може би в крайна сметка щяхме да получим обикновен NullRef или по-лошо, тихо грешни резултати. Притеснението ми е, че не мога да намеря никаква литература за тази промяна в C# 6.0, защото новата синтатична захар и добавянето на функции привличат вниманието. Всичко, което някога съм виждал при промяната на претоварването, е бегло споменаване на nullables, но без примери. Затова питам общността.   -  person Ron Newcomb    schedule 30.05.2015
comment
@RonNewcomb Това със сигурност е критична промяна... И добавя трети начин, по който може да се напише сравнение с enum: (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
Тази статия има много обяснения относно c# 6 blog.slaks.net/2014-05-28/   -  person leat    schedule 22.06.2015
comment
Не съм сигурен, че проблемът е същият, тъй като не публикувате подробностите за грешката, но в моя случай типът на данните беше пропуснат в моята база данни. Имам типа enum като малък int и те създаваха проблем при преобразуването в enum, който променям тези към int в базата данни и работи, отново не съм сигурен дали същият проблем, тъй като не поставяте информация за грешка   -  person Son_of_Sam    schedule 23.06.2015


Отговори (1)


Това няма нищо общо с разрешаването на претоварване. Предишният компилатор преждевременно оптимизира дясната страна на сравнението, като по този начин пропуска кода, съответстващ на изходния израз.

person Neal Gafter    schedule 23.06.2015