Подтвердить что ты не робот

Ошибка компилятора: "ошибка CS0307: переменная" int "не может использоваться с аргументами типа"

Если у меня есть следующий код:

private void Check(bool a, bool b)
{
}

private void Check(int a, int b, int c, bool flag)
{
    Check(a < b, a > (flag ? c : b - 10));
}

Я получаю ошибку времени компиляции при вызове Check(int, int):

ошибка CS0307: переменная 'int' не может использоваться с аргументами типа

Я также получаю следующие ошибки:

ошибка CS0118: 'b' является переменной, но используется как тип
ошибка CS0118:" a" - это переменная, но используется как тип

Почему возникают эти ошибки? Что не так с кодом?

4b9b3361

Ответ 1

Это отличный день для меня. Я никогда не думал, что увижу одну из них в дикой природе! Я только когда-либо видел это в тестах компилятора.

Рассмотрим следующий фрагмент программы:

F(G<A,B>(7));

В С# 1.0 это означало "метод вызова F с двумя аргументами: G<A и B>(7).

Но С# 2.0 добавил дженерики. В С# 2.0 это означает "метод вызова F с одним аргументом. Аргумент - это вызов универсального метода G<A, B> с одним аргументом, 7".

Это было потрясающее изменение. У С# есть несколько эвристик, чтобы попытаться сохранить старые программы, соответствующие этому шаблону, но не все из них.

С# интерпретирует вашу программу

Check(a < b, a > (flag ? c : b - 10));

как вызов Check с одним аргументом: вызов универсального метода a<b, a> с одним аргументом.

Решение для вас просто, как вы обнаружили: просто добавьте в круглые скобки дополнительные аргументы для проверки.

Если вам интересно узнать точное правило, которое использует С#, чтобы попытаться рассказать, когда оно является общим, а когда нет, это:

Если последовательность токенов может быть проанализирована как простое имя, член-доступ или конец доступа к указателю-члену с типом-аргументом-списком, проверяется токен, следующий за закрывающим маркером. Если это один из ( ) ] } : ; , . ? == != | ^, список типов-аргументов сохраняется как часть простого имени, доступа к члену или указателю-члену, а любой другой возможный синтаксический разбор последовательности токенов отбрасывается. В противном случае список типов-аргументов не считается частью простого имени, доступа к члену или указателю-члену, даже если нет другого возможного анализа последовательности токенов. Обратите внимание, что эти правила не применяются при анализе списка типов-аргументов в пространстве имен имен или имен.

Для реализации правил, подобных этому, С# немного сложно разобрать, поверьте мне.