这是一个非常罕见的问题,确实存在很多变通方法,但我想了解实际发生了什么以及它为什么不起作用。
所以我在测试解决方案中有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实例中的值初始化它(就像我在显式转换运算符中一样),它可以正常工作。那么这里有什么问题?
答案 0 :(得分:2)
在6.4.5用户定义的C#语言规范(版本4.0)的显式转换中,它读取:
处理从类型S到类型T的用户定义的显式转换 如下:
•确定类型S0和T0。如果S或T是可空类型,则S0和 T0是它们的基础类型,否则S0和T0等于S和 分别为。
•查找用户定义转换的类型集D. 运营商将被考虑。该集由S0组成(如果S0是a 类或结构),S0的基类(如果S0是一个类),T0(如果是T0 是一个类或结构),以及T0的基类(如果T0是一个类)。
它没有定义编译器将如何"找到类型集"但我认为它会搜索所有相关课程,寻找下一步的候选人:
•查找适用的用户定义和提升转换集 运算符,U。此集由用户定义和提升组成 类或语句声明的隐式或显式转换运算符 D中的结构转换自S包含或包含的类型 到T包含或包含的类型。如果U是空的,那么 转换未定义,发生编译时错误。
这会导致它尝试解析对ClassA的引用。