【发布时间】:2012-04-25 13:32:57
【问题描述】:
考虑以下场景。
我有一个返回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>是否会被退回。
【问题讨论】:
-
我不认为
Wrapped<Something>可以转换为Something。我编译了你的例子,并验证了这一点。第一次转换(变量b)应该失败...... -
我猜你在问为什么
explicit operator T(Wrapped<T> wrapped)不允许转换为传递的具体类型而不仅仅是约束类型。 -
@EthanBrown - 显式转换旨在执行转换,它在情况 B 中正常工作,问题是为什么它不适用于情况 D 或 E
-
I therefore cast the result to Something to use it:为什么你首先需要向下转换为Something?它和Wrapped<T>都实现了ISomething这一事实清楚地表明,至少在某种程度上它们应该是无法区分的。 -
@Anton,希望问题中的修改后的代码能更好地突出我的问题?
标签: c# generics casting operators