Явный оператор литья не работает с ошибкой "сборка не указана"

Это очень необычная проблема, и есть определенно много обходных решений, но я хотел бы понять, что на самом деле происходит и почему она не работает.
Таким образом, у меня есть 3 сборки в тестовом решении, первая сборка имеет тип ClassA:

public class ClassA
{
    public string Name { get; set; }
}

Вторая сборка ссылается на первую сборку и имеет ClassB:

public class ClassB
{
    public string Name { get; set; }

    public static explicit operator ClassA(ClassB objB)
    {
        return new ClassA
        {
            Name = objB.Name
        };
    }
}

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

Теперь последняя сборка ссылается на вторую сборку (а не на первую!) и имеет тип ClassC:

public class ClassC
{
    public string Name { get; set; }

    public static explicit operator ClassB(ClassC objC)
    {
        return new ClassB
        {
            Name = objC.Name
        };
    }
}

который использует явный оператор рассылки по той же причине, что и ClassB.

Теперь интересная часть: если я попытаюсь использовать класс ClassC для ClassB в моем коде, например:

ClassC objC = new ClassC();
ClassB objB = (ClassB)objC;

Я получаю следующую ошибку:

Ошибка 1 Тип "FirstAssembly.ClassA" определен в сборке, на которую не ссылаются. Вы должны добавить ссылку на сборку "FirstAssembly, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null".

Я мог бы легко создать новый экземпляр ClassB и просто инициализировать его со значениями из экземпляра ClassC (например, я делаю это в явном операторе литья), и он будет работать нормально. Итак, что здесь не так?

Ответы

Ответ 1

В разделе 6.4.5 Пользовательские явные преобразования в языке С# Language Specification (версия 4.0) читают:

Обработанное пользователем явное преобразование типа S в тип T обрабатывается следующим образом:

• Определите типы S0 и T0. Если S или T являются типами NULL, S0 и T0 - их базовые типы, иначе S0 и T0 равны S и T соответственно.

• Найдите набор типов, D, из которых определяется пользовательское преобразование операторы будут рассмотрены. Этот набор состоит из S0 (если S0 является class или struct), базовые классы S0 (если S0 - класс), T0 (если T0 является классом или структурой) и базовыми классами T0 (если T0 - класс).

Он не определяет , как компилятор будет "Найти набор типов", но я думаю, что он ищет все соответствующие классы, которые ищут кандидатов для следующего шага:

• Найдите набор применимых пользовательских и отмененных преобразований операторов, U. Это множество состоит из определяемого пользователем и снятого неявные или явные операторы преобразования, объявленные классами или структур в D, которые преобразуются из типа, охватывающего или охватываемого S к типу, охватывающему или охватываемому Т. Если U пусто, преобразование undefined и возникает ошибка времени компиляции.

Это заставляет попытаться разрешить ссылку на ClassA.