MSTest 4.4.1 исправляет неоднозначные вызовы Assert с CS0121, которые 4.4.0 сломал ниже C# 14
MSTest 4.4.0 добавил перегрузки Span<T> и ReadOnlySpan<T> в Assert.Contains и Assert.DoesNotContain, из-за чего обычные проверки массивов и строк стали падать с CS0121 на net8.0, net9.0 и в любом проекте ниже C# 14. MSTest 4.4.1, опубликованный 2026-09-16, добавляет точные перегрузки для массивов и ограниченные перенаправляющие перегрузки. Две формы вызова с явным обобщённым аргументом по-прежнему не компилируются.
Если вы обновили MSTest до 4.4.0 в проекте, нацеленном на net8.0 или net9.0, тестовый проект мог перестать компилироваться на строках, которые годами не менялись. MSTest 4.4.1, опубликованный в NuGet 2026-09-16, это исправляет. Ниже разобрано, что сломалось, какую матрицу версий я получил при проверке и какие две формы вызова 4.4.1 всё ещё не покрывает.
Перегрузки Span, которые умеет ранжировать только C# 14
MSTest 4.4.0 добавил перегрузки Span<T> и ReadOnlySpan<T> рядом с существующими IEnumerable<T> в Assert.Contains и Assert.DoesNotContain. В C# 14 первоклассные преобразования span дают компилятору правила разрешения неоднозначности для массивов и строк, поэтому он выбирает перегрузку. Ниже C# 14 преобразование T[] в Span<T> существует только как пользовательский op_Implicit, и ни одна из перегрузок не оказывается лучше. Issue #11022 сообщил об этом на следующий день после выхода 4.4.0:
error CS0121: The call is ambiguous between the following methods or properties:
'Assert.Contains<T>(T, System.Collections.Generic.IEnumerable<T>, string?, string, string)' and
'Assert.Contains<T>(T, System.Span<T>, string?, string, string)'
Поскольку для net8.0 по умолчанию используется C# 12, а для net9.0 C# 13, эти TFM ломаются сразу. То же самое происходит с проектом net10.0, закреплённым на более старой LangVersion.
Матрица версий
Я скомпилировал один и тот же файл с каждой версией на SDK 10.0.302:
int[] ids = [1, 2, 3];
string name = "Marius";
Assert.Contains(2, ids);
Assert.DoesNotContain(4, ids);
Assert.DoesNotContain('z', name);
Assert.Contains<int>(2, ids);
| MSTest | Цель / язык | Результат |
|---|---|---|
| 4.3.3 | net8.0, net10.0 | собирается |
| 4.4.0 | net10.0 (C# 14) | собирается |
| 4.4.0 | net8.0, net9.0 или net10.0 с LangVersion 12 | 4 x CS0121 |
| 4.4.0 | net8.0 с LangVersion 14 | собирается |
| 4.4.1 | net8.0, net10.0 | собирается |
На 4.4.0 падают все четыре вызова, включая явный Contains<int> и случай со string. Единственный обходной путь для 4.4.0 заключается в повышении LangVersion до 14 на более старом TFM, а такая комбинация не поддерживается. Настоящее исправление состоит в обновлении:
<PackageReference Include="MSTest" Version="4.4.1" />
Если вы используете MSTest.Sdk, обновите версию в global.json или в атрибуте Sdk="MSTest.Sdk/4.4.1".
Как 4.4.1 это исправляет и что остаётся за бортом
PR #11038 добавляет точные перегрузки T[] в каждое затронутое семейство методов Assert. Точное совпадение выигрывает у обоих преобразований, поэтому вызовы на массивах, как с выводом типа, так и с явным аргументом, снова разрешаются. Кроме того, PR добавляет ограниченные перенаправляющие перегрузки, благодаря которым вызовы с выводом типа продолжают работать для других типов, преобразуемых в span, например string, ArraySegment<T> и ваших собственных коллекций. Они перенаправляют вызов в существующий код для IEnumerable<T>, так что поведение совпадает с 4.3.3.
В PR сказано, что явные вызовы с <T> для типов, не являющихся массивами, в его рамки не входят, и моя проверка на 4.4.1 с net8.0 это подтверждает:
var seg = new ArraySegment<int>(ids);
Assert.Contains(2, seg); // OK
Assert.Contains(2, ids.AsSpan()); // OK
Assert.Contains<int>(2, seg); // CS0121
Assert.Contains<char>('M', name); // CS0121
Уберите аргумент типа, чтобы вывод типа выбрал перенаправляющую перегрузку, или приведите значение к IEnumerable<T>.
Тот же релиз также сужает набор того, что генератор исходного кода MSTest помечает как корни для тримминга и Native AOT, и исправляет генерируемые литералы для перечислений, узких целочисленных типов, NaN и управляющих символов. Если вы включили генератор после того, как MSTest 4.4 вывел его из предварительной версии, это ещё одна причина перейти на 4.4.1.
Comments
Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.