Явный оператор литья не работает с ошибкой "сборка не указана"
Это очень необычная проблема, и есть определенно много обходных решений, но я хотел бы понять, что на самом деле происходит и почему она не работает.
Таким образом, у меня есть 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.