Почему я вынужден ссылаться на типы в неиспользуемых конструкторах? - PullRequest
6 голосов
/ 02 сентября 2010

Допустим, у меня есть класс (ClassA), содержащий один метод, который вызывает конструктор другого класса, например:

public class ClassA
{
    public void CallClassBConstructor()
    {
        using(ClassB myB = new ClassB()) {...}
    }
}

Класс ClassB выглядит следующим образом:

public class ClassB : IDisposable
{
    public ClassB(){}
    public ClassB(string myString){}
    public ClassB(ClassC myC){}
    public void Dispose() {...}
}

... и ClassC еще проще:

public class ClassC{}

Если я помещу эти классы в их собственную сборку и скомпилирую все решение, я не получу никаких ошибок.Но если я заменю оператор using на следующее:

using(ClassB myB = new ClassB("mystring")){...}

, я получаю ошибку компиляции, в которой мне предлагается добавить ссылку на [mynamespace].ClassC в ClassA.Поскольку я вообще не вызываю ClassB(ClassC myC), для меня это не имеет никакого смысла - почему я должен включать типы других конструкторов независимо от того, использую я их или нет?Что если ClassC был включен в лицензированную или труднодоступную сборку?Это пример плохого дизайна, которого разработчики должны избегать, или я что-то здесь упускаю?

Ответы [ 3 ]

9 голосов
/ 02 сентября 2010

Это связано с разрешением перегрузки метода при вызове конструктора ClassB.

Когда вы вызываете конструктор без параметров, конфликт не возникает.Есть только один кандидат, поэтому он выбран.В этом случае нет необходимости для ClassA ссылаться на ClassC.

Однако, когда вы вызываете конструктор с одним параметром, вначале оба однопараметрических конструктора являются кандидатами.Чтобы разрешить этот вызов, компилятору необходимо знать о ClassC.Для всего, что вы знаете, ClassC может содержать, например, оператор неявного преобразования.

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

1 голос
/ 02 сентября 2010

Это потому, что ClassC, который вы поместили в отдельную сборку, является частью открытого интерфейса ClassB, поскольку он является параметром одного из конструкторов.Вы должны ссылаться на содержащую сборку этого типа, иначе компилятор не знает, как разрешить информацию о типе.В этом конкретном случае компилятор должен разрешить все типы параметров из всех перегрузок конструктора, чтобы он мог выбрать правильный, но это не является проблемой перегрузки члена как таковой.Это происходит каждый раз, когда компилятор должен разрешить информацию о типе.Это может произойти и с типами возврата.

1 голос
/ 02 сентября 2010

Чтобы разрешить перегрузки конструктора, компилятору необходимо знать, какие типы задействованы. То есть ему нужно знать ClassC, чтобы выбрать правильную перегрузку конструктора для ClassB.

...