Как может возникнуть двусмысленность между методом getter и методом с одним аргументом?
Не могу поверить, что я никогда не сталкивался с этим раньше, но почему я получаю ошибку компилятора для этого кода?
public class Main
{
public Main()
{
var ambiguous = new FooBar(1);
var isConfused = ambiguous.IsValid; // this call is ambiguous
}
}
public class FooBar
{
public int DefaultId { get; set; }
public FooBar(int defaultId)
{
DefaultId = defaultId;
}
public bool IsValid
{
get { return DefaultId == 0; }
}
public bool IsValid(int id)
{
return (id == 0);
}
}
Вот сообщение об ошибке:
Неоднозначность между 'FooBar.IsValid' и 'FooBar.IsValid(int)'
Почему это неоднозначно?
Я думаю, что есть две причины, почему это не должно быть двусмысленным:
- После
IsConfused
нет парафаз.
- Нет аргумента int для
IsConfused
.
Где двусмысленность?
Ответы
Ответ 1
Ошибка возникает из-за неоднозначности, поскольку она объявлена с помощью var
. Это может быть:
bool isConfused = ambiguous.IsValid;
Или:
Func<int, bool> isConfused = ambiguous.IsValid;
Использование var
требует, чтобы компилятор мог определить точное значение, и в этом случае есть две возможности.
Однако, если вы удалите var
, вы по-прежнему получите (другую) ошибку, так как вы не можете иметь двух членов с тем же именем, одно свойство и один метод.
Ответ 2
Сбив с толку, вы получите это конкретное сообщение, но неправомерно иметь двух членов с тем же именем (кроме перегрузки метода). Здесь ваше свойство и метод имеют одно и то же имя. Это по той же причине, что вы не можете иметь свойство и внутренний класс с тем же именем. Поля, свойства, методы и внутренние классы являются членами входящего типа и должны иметь уникальные имена.
Ответ 3
Вы получите сообщение об ошибке "FooBar уже содержит определение для IsValid"
Ответ 4
Во-первых, может показаться, что компилятор всегда мог выяснить, вы вызываете метод или используете свойство - в конце концов, после этого метод имеет круглые скобки, а свойство не имеет.
Это не задерживается. Вы можете использовать метод без круглых скобок:
void Foo() { ... }
void Bar(Action action) { ... }
Bar(Foo);
И вы можете использовать свойство с круглыми скобками:
Action MyProperty { get; set; }
MyProperty();
Единственный способ убедиться в отсутствии двусмысленности в том, чтобы запретить использование метода и свойства с тем же именем.