MSBuild v14 компилирует семантически неправильную сборку в некоторых редких случаях

После обновления среды сборки один из наших тестов Smoke сломался в TeamCity. Исследование показало, что из того же исходного кода

  • C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe создает правильный двоичный файл
  • C:\Program Files (x86)\MSBuild\14.0\bin\MSBuild.exe создает неправильные двоичные файлы

Когда это происходит

  • "params object []" используется
  • передается только одно значение, не будучи явно заключенным в массив
  • Именованные параметры используются
  • в другом порядке, чем в сигнатуре метода

Пример кода для воспроизведения

static void Main(string[] args)
{
    var customerId = Guid.NewGuid();

    // Produces buggy code when compiled with MSBuild v14
    TestMethodWithParams(args: customerId, whatever: "foo");

    //All the calls below result correct behavior, regardless of the version of MSBuild, order and naming of parameters
    TestMethodWithParams("foo", customerId);
    TestMethodWithParams(whatever: "foo", args: customerId);

    TestMethodWithParams(args: new object[] { customerId }, whatever: "foo");
    TestMethodWithParams("foo", new object[] { customerId });
    TestMethodWithParams(whatever: "foo", args: new object[] {customerId});
}

private static void TestMethodWithParams(string whatever, params object[] args)
{
    Console.WriteLine("args: '{0}'", args);
}

Что именно происходит

Неверная версия просто проглатывает единственный параметр, значение null передается. Декомпилированный код показывает разницу:

В правильном двоичном файле:

Guid guid = Guid.NewGuid();
Program.TestMethodWithParams("foo", new object[]
{
    guid
});

В неправильном двоичном файле:

Guid guid = Guid.NewGuid();
object obj;
Program.TestMethodWithParams("foo", new object[]
{
    obj // <- this is and will always be null
});

Как исправить его

Когда мы завернули единственный параметр в массив объектов, проблема исчезла. Другим вариантом было бы не использовать именованные аргументы и/или убедиться, что порядок появления параметров одинаковый в вызове и в сигнатуре.

НО. Основная проблема заключается в том, что мы не можем вернуться к более старому MSBuild (...) и проверять всю базу кода (и проходить через каждый из бинарных файлов в толпе наших пакетов NuGet) нелегко и эффективное решение. Более того, такая ошибка может быть повторно введена в кодовую базу в любое время позже случайно. Поэтому лучшим решением, вероятно, было бы как-то исправить MSBuild.

Кто-нибудь испытал что-то подобное? Может быть, это ошибка в MSBuild? Идеи?

Ответ 1

Как я уже упоминал о проблеме GitHub, я считаю, что это ошибка, которая первоначально была объявлена ​​как # 4197 и была исправлена ​​в Roslyn 1.1.

Ответ 2

Благодарим вас за информацию и предложения. Вы делились сведениями, которые помогли нам выявить эту проблему. Оказалось, что установка "Microsoft Build Tools 2015 с обновлением 2" решила нашу проблему.

Спасибо всем. /David