.ctor неоднозначен, потому что в классе существует несколько видов членов с таким именем.

Я повторяю ситуацию, с которой сталкиваюсь.

Допустим, у нас есть сборка с классом C#:

public class Program
{
    int n = 0;

    public void Print()
    {
        Console.WriteLine(n);
    }

    public Program()
    {
    }

    public Program(int num = 10)
    {
        n = num;
    }
}

Мы ссылаемся на приведенную выше сборку в проекте VB.NET и пытаемся создать экземпляр класса Program:

Module Module1 
    Sub Main()
        Dim p As New Program()
        p.Print()
        p = New Program(20)
        p.Print()
        Console.ReadLine()
    End Sub
End Module

Проект VB.NET не компилируется, выдавая ошибку:

'.ctor' неоднозначен, так как в классе 'ConsoleApplication2.Program' существует несколько видов членов с таким именем.

Из сообщения об ошибке видно, что компилятор VB.NET не уверен, какой конструктор вызывать, поскольку один конструктор не имеет параметров, а другой — с одним необязательным параметром. Эта проблема возникает в VS2010/.NET 4, а не в VS2012/.NET 4.5. Также в C# проблем не возникает, он успешно компилирует и запускает код инициализации объекта класса Program.

Есть ли способ создать экземпляр класса Program в VB.NET + VS2010/.NET 4 без изменения конструкторов?


person Brij    schedule 20.02.2014    source источник
comment
Зачем тебе эта конструкция? Есть ли способ, которым я упускаю возможность вызвать второй конструктор и заставить компилятор использовать параметр по умолчанию?   -  person Damien_The_Unbeliever    schedule 20.02.2014
comment
Этот код пахнет. Это амбициозно без VB. Как вы думаете, каким должно быть значение num для такого использования, как var program = new Program()? Вы необязательно хотели, чтобы num было 10, или это конструктор по умолчанию, где num поле инициализируется равным 0???   -  person Sinatr    schedule 20.02.2014
comment
@Sinatr, это повторение ситуации, с которой я столкнулся. Я написал это таким образом, чтобы различать вывод и определять, какой конструктор вызывается в C#.   -  person Brij    schedule 20.02.2014
comment
Похоже, компилятор VB делает мне одолжение.   -  person Jodrell    schedule 20.02.2014
comment
@ Джодрелл, полностью согласен, у нас должно быть это и на C # :)   -  person Brij    schedule 20.02.2014


Ответы (2)


Проблема в определениях ваших конструкторов в классе Program

Поскольку аргумент второго является необязательным, оба являются кандидатами при вызове с использованием New Program(). Это создает двусмысленность.

Вместо этого определите свои конструкторы, используя такой шаблон:

public Program()
    : this(10)
{
}

public Program(int num)
{
    n = num;
}

или просто один конструктор:

public Program(int num = 10)
{
    n = num;
}

(Лично я предпочитаю первый из них).

person Jon Egerton    schedule 20.02.2014
comment
@Jon_Egerton изменение конструктора решит проблему, но можем ли мы вызвать конкретный конструктор, не внося никаких изменений в класс C # Program? Кроме того, неоднозначность возникает не в C#, а в VB.NET. Также в VB.NET это происходит в .NET 4.0, а не в .NET 4.5. - person Brij; 20.02.2014
comment
Честно говоря, не уверен - у меня, кажется, неясности проскальзывают раньше или начинают ошибаться через некоторое время. Однако посмотрите на это с другой стороны. Когда вы вызываете New Program(), что вы ожидаете от n? - 0 или 10? Они неоднозначны не только на уровне кода, но и на концептуальном уровне. - person Jon Egerton; 20.02.2014
comment
Когда вы говорите .Net 4, это было в VS2010 или VS2012/13? - person Jon Egerton; 20.02.2014
comment
См. ответ Дэмиена. В C# это было бы обработано для всех этих версий. Для VB это недавнее дополнение. Тем не менее, это мусорная конструкция - вы никогда не получите значение по умолчанию, равное 10! - person Jon Egerton; 20.02.2014

Лучшим способом было бы изменить реализацию конструктора, как написал @JonEgerton. Если это невозможно, вы можете попробовать следующие - не очень красивые - обходные пути:

  • Если вы знаете внутреннюю реализацию класса Program, вы можете просто вызвать конструктор с int-Parameter со значением, которое присваивает конструктор без параметров, в вашем примере Dim p As New Program(0). Это означает, что вам нужно быть осторожным в отношении последующих изменений в реализации конструкторов класса Program, поскольку они не будут отражены в вашей реализации. Например, если разработчики класса Program изменят значение, назначенное в конструкторе без параметров, ваше решение по-прежнему будет присваивать значение 0.
  • Поскольку C#, по-видимому, обрабатывает создание по-другому, вы также можете добавить класс C# (например, в библиотеку классов C#), который создает для вас экземпляр программы и возвращает его в ваш код. Хотя это может означать добавление библиотеки классов в ваше решение с единственной целью и, следовательно, не очень красивый подход, более поздние изменения в реализации класса Program также будут отражены в вашей программе.
person Markus    schedule 20.02.2014