Мы находимся в процессе миграции приложения на .NET 4.0 (с 3.5). Одна из проблем, с которой мы сталкиваемся, воспроизводима только при очень определенных условиях:
Под этим я подразумеваю, если я отключу оптимизацию и установлю полную информацию об отладке, проблема исчезнет.
Рассматриваемый код отлично работает в .NET 3.5, в режиме выпуска с включенной оптимизацией и т. д., и работал долго времени.
Я действительно не хочу предполагать, что в компиляторе C # есть ошибка, поэтому на самом деле у меня вопрос, есть ли какие-нибудь методы, которые я могу использовать для отслеживания того, что мы можем делать неправильно, чтобы вызвать неправильную оптимизацию?
Я ' m в процессе попытки сузить эту проблему до небольшого тестового примера, поэтому я могу опубликовать здесь некоторый код.
Изменить:
Я отследил проблему до следующего:
У нас есть этот код в конструкторе формы:
public ConnectionForm()
{
LocalControlUtil.Configure("ConnectionForm", "Username", usernameLabel);
LocalControlUtil.Configure("ConnectionForm", "Password", passwordLabel);
LocalControlUtil.Configure("ConnectionForm", "Domain", domainLabel);
LocalControlUtil.Configure("ConnectionForm", "Cancel", cancelButton);
LocalControlUtil.Configure("ConnectionForm", "OK", okButton);
}
Эти вызовы относятся к некоторому пользовательскому коду локализации. Конструктор этой формы вызывается из другой сборки. Метод LocalControlUtil.Configure
вызывает Assembly.GetCallingAssembly ()
, который возвращает правильное значение для всех вышеперечисленных вызовов , кроме последнего .
Я могу изменить порядок строк выше, добавить новые или удалить текущие, и каждый раз это последняя строка, которая не работает.
Я предполагаю, что это JIT, вставляющий последний вызов метода в место, где был конструктор называется (в другой сборке). Добавление [MethodImpl (MethodImplOptions.NoInlining)]
в конструктор выше решает проблему.
Кто-нибудь знает, почему это происходит? Мне кажется странным, что может быть встроена только последняя строка. Это новое поведение в .NET 4.0?
Редактировать 2:
Я сузил это до исключения хвостового вызова, как я полагаю, вызванного новым хвостовым вызовом в .NET 4 .
В приведенном выше коде последний вызов LocalControlUtil.Configure
в конструкторе удаляется и помещается в вызывающий метод, который находится в другой сборке. Поскольку метод вызывает Assembly.GetCallingAssembly
, мы не получаем обратно правильную сборку.
Есть ли способ остановить компилятор (или JIT, или что-то еще) от устранения хвостового вызова?