Ответ 1
Я получил обновление от MS, что это действительно настоящая проблема и исправлено в предстоящей версии x64 jiter.
Я искал вам код, который не работал. Все выглядит отлично, за исключением следующей строки.
Transport = Transport?? MockITransportUtil.GetMock(true);
Перед выполнением этой строки Transport имеет значение null. Я вижу, что GetMock выполняется, и что он возвращает ненулевой объект. После этой строки Transport по-прежнему остается null;
Я посмотрел на ИЛ, который был сгенерирован, и это выглядит хорошо для меня.
IL_0002: ldarg.0
IL_0003: ldfld class [Moq]Moq.Mock`1<class [CommLibNet]CommLibNET.ITransport> Curex.Services.Common.UnitTests.Messaging.TestIGuaranteedSubscriptionBase::Transport
IL_0008: dup
IL_0009: brtrue.s IL_0012
IL_000b: pop
IL_000c: ldc.i4.1
IL_000d: call class [Moq]Moq.Mock`1<class [CommLibNet]CommLibNET.ITransport> Curex.Services.Common.UnitTests.Mocking.MockITransportUtil::GetMock(bool)
IL_0012: stfld class [Moq]Moq.Mock`1<class [CommLibNet]CommLibNET.ITransport> Curex.Services.Common.UnitTests.Messaging.TestIGuaranteedSubscriptionBase::Transport
Мы видим, что функция get вызвана, и stfld должен принять возвращаемое значение и установить поле.
Итак, я посмотрел на сборку, которую я вижу, когда вызов сделан, но похоже, что возврат в RAX сбрасывается следующим вызовом и теряется.
Transport = Transport?? MockITransportUtil.GetMock(true);
000007FE9236F776 mov rax,qword ptr [rbp+0B0h]
000007FE9236F77D mov rax,qword ptr [rax+20h]
000007FE9236F781 mov qword ptr [rbp+20h],rax
000007FE9236F785 mov rcx,qword ptr [rbp+20h]
000007FE9236F789 mov rax,qword ptr [rbp+0B0h]
000007FE9236F790 mov qword ptr [rbp+28h],rax
000007FE9236F794 test rcx,rcx
000007FE9236F797 jne 000007FE9236F7AC
000007FE9236F799 mov cl,1
000007FE9236F79B call 000007FE92290608
//var x = ReferenceEquals(null, Transport) ? MockITransportUtil.GetMock(true) : Transport;
ListerFactory = ListerFactory ?? MockIListenerUtil.GetMockSetupWithAction((a) => invokingAction = a);
000007FE9236F7A0 mov qword ptr [rbp+30h],rax
000007FE9236F7A4 mov rax,qword ptr [rbp+30h]
000007FE9236F7A8 mov qword ptr [rbp+20h],rax
000007FE9236F7AC mov rcx,qword ptr [rbp+28h]
если я использую оператор if или оператор?: оператор работает отлично.
Visual Studio 2013
Я создал минимальное воспроизведение psudo.
class simple
{
public A MyA = null;
public B MyB = null;
public void SetUp()
{
MyA = MyA ?? new A();
MyB = new B();// Put breakpoint here
}
}
Если вы установите контрольную точку в указанной строке и посмотрите на значение MyA в отладчике, она будет по-прежнему равна null (только при построении в x64). если вы выполните следующую строку, оно установит значение. Я не смог воспроизвести оценку, которая вообще не происходит. Его очень ясно в разборке, выполнение для следующей строки началось до назначения.
Вот ссылка на сайт ms connect
Я получил обновление от MS, что это действительно настоящая проблема и исправлено в предстоящей версии x64 jiter.
MyB = new B();// Put breakpoint here
Проблема - это точка останова, а не генерация кода. X64 jitter flubs this, он генерирует неточную информацию для отладки. Он неправильно выводит информацию о номере для инструкции, используя код, который все еще является частью предыдущего оператора.
Вы можете сказать, что из разборки, которую вы опубликовали, код по адресам F7A0-F7A8 все еще является частью выражение. Ветвь к F7AC является реальной, когда начинается следующий оператор. Поэтому он должен был сказать, что F7AC был началом следующего утверждения, а не F7A0.
Последствия этой ошибки в том, что отладчик никогда не может остановиться в точке останова. Вы можете это увидеть сами, изменив свой репродуцирующий код и напишите public A MyA = new A();
. И если он остановится, то назначение еще не выполнено. Таким образом, вы по-прежнему видите переменную с предыдущим значением, null в вашем случае. Один шаг разрешает его, хотя это зависит от того, как выглядит следующий оператор.
Будьте уверены, что это происходит неправильно при отладке, программа по-прежнему работает правильно. Просто держите эту причуду в виду, афайк это только пойдет не так для??? оператор. Вы можете сказать, что он не используется много:) Хотя большинство программистов только отлаживают 32-битную версию своей программы, настройки проекта по умолчанию в значительной степени поощряют ее.
Проблема решается по мере того, как мы говорим, не ожидайте, что ваш отчет Connect будет иметь влияние, Microsoft хорошо знает об этой ошибке. Команда джиттера в Microsoft полностью перезаписала джиттер x64, в настоящее время она находится в CTP2. Я бы оценил еще год или около того, прежде чем он будет выпущен.