Как может быть двусмысленность между получателем свойства и методом с одним аргументом? - PullRequest
12 голосов
/ 07 июля 2011

Не могу поверить, что никогда не сталкивался с этим раньше, но почему я получаю ошибку компилятора для этого кода?

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)'

Почему это неоднозначно?

Я думаю тамЕсть две причины, по которым он не должен быть двусмысленным:

  1. После IsConfused.
  2. нет круглых скобок. Для IsConfused.
* нет аргумента int1023 * Где двусмысленность?

Ответы [ 4 ]

15 голосов
/ 07 июля 2011

Ошибка возникает потому, что она неоднозначна, поскольку она объявлена ​​с использованием var.Это может быть:

bool isConfused = ambiguous.IsValid;

Или:

Func<int, bool> isConfused = ambiguous.IsValid;

Использование var требует, чтобы компилятор мог определить точное значение, и в этом случае есть две возможности.

Однако, если вы удалите var, вы все равно получите (другую) ошибку, поскольку у вас не может быть двух членов с одинаковым именем, одного свойства и одного метода.

6 голосов
/ 07 июля 2011

Это сбивает с толку, что вы получите это конкретное сообщение, но не разрешено иметь двух членов с одинаковым именем (исключая перегрузку метода).Здесь ваше свойство и метод имеют одно и то же имя.Это та же самая причина, по которой вы не можете иметь свойство и внутренний класс с одинаковым именем.Поля, свойства, методы и внутренние классы являются членами включающего типа и должны иметь уникальные имена.

0 голосов
/ 07 июля 2011

Сначала может показаться, что компилятор всегда может определить, вызываете ли вы метод или используете свойство - в конце концов, у метода есть скобки после него, а у свойства - нет.

Хотя это не так. Вы можете использовать метод без скобок:

void Foo() { ... }
void Bar(Action action) { ... }

Bar(Foo);

И вы можете использовать свойство с круглыми скобками:

Action MyProperty { get; set; }

MyProperty();

Единственный способ убедиться, что нет двусмысленности, это запретить использование метода и свойства с одинаковым именем.

0 голосов
/ 07 июля 2011

Вы получите сообщение об ошибке «FooBar уже содержит определение для IsValid»

...