Неоднозначный вызов функции / конструктора в C # - PullRequest
7 голосов
/ 19 мая 2010

Следующий код вызывает ошибку компилятора, так как это неоднозначный вызов, но проблема, если мы используем object вместо ArrayList, ошибка не возникает и версия string работает нормально; У вас есть объяснение этому?

class A
{
    public A(string x)
    {
        Console.WriteLine("string");
    }
    public A(ArrayList x)
    {
        Console.WriteLine("ArrayList");
    }

}
    static void Main(string[] args)
        {
            A o = new A(null);
        }

Ответы [ 6 ]

16 голосов
/ 19 мая 2010

Причина, по которой ваш код работает нормально, если вы измените конструктор, которому требуется ArrayList, чтобы принять object, заключается в том, что компилятор C # выберет наиболее подходящий тип.В случае string / object, string фактически выводит из object и поэтому является "более конкретным" и будет выведено компилятором.При string против ArrayList это яблоки и апельсины: любой может быть нулевым, но ни один не является более «специфичным», чем другой.

4 голосов
/ 19 мая 2010

Я могу ошибаться, но я думаю, что причина, по которой он работает, когда вы изменяете ArrayList на объект, заключается в том, что строка наследуется от объекта и решает использовать более конкретную версию строки. Когда это строка и ArrayList, он не знает, какой из них использовать.

3 голосов
/ 19 мая 2010

null может представлять либо string, либо ArrayList. Нет никакой информации о том, какую версию метода (в данном случае конструктора) вы имели в виду.

Вы можете заставить его использовать определенный, разыграв:

static void Main(string[] args)
    {
        A o = new A((string)null);
    }

... или альтернативно реализовать конструктор, который ведет себя так, как вы хотите (без параметров)

2 голосов
/ 21 марта 2014

Вы можете справиться с этой ситуацией, используя default , например ключевое слово, и код будет:

A o = new A(default(ArrayList)); 

Или

A o = new A(default(string)); 
1 голос
/ 19 мая 2010

ArrayList и string являются типами nullable. Это смущает компилятор.

Если у вас есть два конструктора, скажите один, который принимает обнуляемый тип, например ArrayList и другие, которые принимают non-nullable типа, например int. Код скомпилирует и выберет конструктор с типом nullable.

Но если у вас есть более одного конструктора, который принимает тип nullable, тогда как @ Дэн Тао сказал это яблоки и апельсины: любой из них может быть нулевым, но ни один не является более "конкретным", чем другой.

например:

class A
{
    public A(int x)
    {
        Console.WriteLine("string");
    }
    public A(ArrayList x)
    {
        Console.WriteLine("ArrayList");
    }

}

Этот код компилируется но если вы измените public A(int x)t на public A(int? x), это НЕ будет.

1 голос
/ 19 мая 2010
  1. Конечно, это неоднозначно: null может быть либо string, либо ArrayList. Вам нужно будет квалифицировать его, как (string) null.
  2. Знаете ли вы, что ArrayList устарела? Вместо этого вы должны использовать один из универсальных типов коллекций
...