请考虑以下情况。
我有一个返回ISomething
的方法,但可能是Something
或Wrapped<Something>
。
因此,我将结果转换为Something
以使用它,但它失败了,对于为什么或如何解决它的任何帮助将不胜感激。
class Program
{
static void Main(string[] args)
{
var a = new DerivedSomething();
var b = (DerivedSomething)new Wrapped<DerivedSomething>(a); //success
var c = (DerivedSomething)_GetSomething(false); //success, obsiously!
var d = (DerivedSomething)_GetSomething(true); //Unable to cast object of type 'test_bed.Wrapped`1[test_bed.DerivedSomething]' to type 'test_bed.DerivedSomething'.
var e = (DerivedSomething)(ISomething)new Wrapped<DerivedSomething>(a); //Unable to cast object of type 'test_bed.Wrapped`1[test_bed.DerivedSomething]' to type 'test_bed.DerivedSomething'.
var works = ((DerivedSomething)_GetSomething(false)).DoSomethingElse();
var fails = ((DerivedSomething)_GetSomething(true)).DoSomethingElse(); //cast exception
}
private static ISomething _GetSomething(bool wrap)
{
var something = new DerivedSomething();
return wrap ? new Wrapped<DerivedSomething>(something) : (ISomething)something;
}
}
public interface ISomething
{
void DoSomething();
}
public abstract class Something : ISomething
{
public void DoSomething()
{
//some code
}
}
public class DerivedSomething : Something
{
public void DoSomething()
{
//some code
}
public void DoSomethingElse()
{
//some code
}
}
public class Wrapped<T> : ISomething
where T : ISomething
{
private readonly T _something;
public Wrapped(T something)
{
_something = something;
}
public void DoSomething()
{
_something.DoSomething();
}
public static explicit operator T(Wrapped<T> wrapped)
{
return wrapped._something;
}
}
如果在尝试强制转换时将该类型作为界面公开,那么似乎找不到运算符?
'简单'的解决方案是编写一个'展开'功能,可以选择将Wrapped<Something>
展开到Something
,但我更愿意使用运算符。
修改
我认为问题的症结在于:_GetSomething()
之外我不知道是否会返回Something
或Wrapped<Something>
。
答案 0 :(得分:4)
显式转换在编译时绑定(额外的提示是转换运算符是静态的)。
尝试
var f = (Something)(Wrapped<Something>)_GetSomething(true);
这成功了
在您的情况下,编译器只知道您的类型为ISomething
,并且不知道如何将ISomething
转换为Something
,除非该事件发生为Something
已经
通过将public class Wrapped<T> : ISomething
更改为public class Wrapped<T> : Something
您的示例执行正常,但由于Wrapped<T>
已经是T
,因此不会调用您的演员。
注意:强>
explicit operator
不是强制转换,而是类型转换,它是一个调用的方法,并且该方法基于编译时类型(在您的情况下为ISomething
)来解析。令人困惑的是,类型转换与类型转换具有相同的语法。转换只是将现有对象分配给兼容类型的不同变量,而类型转换实际上返回一个新对象。
答案 1 :(得分:2)
你施放的操作符如下所示:
public static explicit operator T(Wrapped<T> wrapped)
{
return wrapped._something;
}
你就像
一样var d = (Something)_GetSomething(true); //FAILS!
您无法转换为Something
,因为Something
是T:ISomething
的具体实现。为了完成这项工作,你需要写:
var d = (ISomething)_GetSomething(true); //SUCCESS!
或
如果确实想要使用具体的类型,您可以定义类似的通用:
public class Wrapped<T> : Something //Something and NOT ISomething
where T : ISomething
{
.....
.....
}
答案 2 :(得分:0)
var d = (Something)(Wrapped<Something>)_GetSomething(true);
var e = (Something)new Wrapped<Something>(a);