考虑以下场景。
我有一个返回 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;
}
}
似乎如果类型在尝试转换时作为接口(interface)公开,则找不到运算符?
“简单”的解决方案是编写一个“解包”函数,它可以选择解包 Wrapped<Something>
至 Something
,但如果可能的话,我更愿意使用运算符。
编辑
我认为问题的症结在于:_GetSomething()
之外我不知道是否Something
或 Wrapped<Something>
将被退回。
最佳答案
显式转换在编译时绑定(bind)(额外提示是转换运算符是静态的)。
尝试
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
)。类型转换与类型转换具有相同的语法,这是一个混淆的根源。转换只是将现有对象分配给兼容类型的不同变量,而类型转换实际上返回一个新对象。
关于c# - 泛型和显式/隐式运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10136543/