为什么C#中的隐式类型转换失败?

5

背景:

假设我有以下类:

class Wrapped<T> : IDisposable
{
    public Wrapped(T obj)  { /* ... */ }

    public static implicit operator Wrapped<T>(T obj)
    {
        return new Wrapped<T>(obj);
    }

    public void Dispose()  { /* ... */ }
}

正如您所看到的,它为 TWrapped<T> 提供了一个隐式类型转换运算符。最终,我希望能够按照以下方式使用这个类:

interface IX  { /* ... */ }

class X : IX  { /* ... */ }

...

IX plainIX = new X();

using (Wrapped<IX> wrappedIX = plainIX)
{
    /* ... */
} 

问题:

然而,上述using语句中的类型转换失败了。虽然我可以直接将new X()分配给wrappedIX,但我不能将任何类型为IX的内容分配给它。编译器将抱怨以下错误:

编译器错误CS0266:无法隐式地将类型“IX”转换为“Wrapped<IX>”。存在显式转换(是否缺少转换?)

我不明白这是什么问题。这里有什么问题?


如果将“IX plainIX = new X();”替换为“X plainIX = new X();”,则可编译。 - Nagg
1个回答

7

我认为这是因为IX是一个接口。编译器可能认为Wrapped<IX>已经派生出了类型为IX的值(即使Wrapped<T>是密封的),因此它不使用转换。

细节非常复杂,在C# 3.0规范的6.4.3和6.4.4节中有详细说明。基本上,由于IX是一个接口,它没有被任何类型“包含”,这意味着6.4.4后面的步骤失败了。

我建议您创建一个非泛型类型Wrapped,其中包含此方法:

public static Wrapped<T> Of<T>(T item)
{
    return new Wrapped<T>(item);
}

然后你只需要写下以下内容:
using (Wrapped<IX> wrappedIX = Wrapped.Of(plainIX))

基本上,转换可能会因为各种原因有点棘手——简单的方法通常更容易理解,以我个人的看法。


T被正确地用out修饰时,这将适用于C#4,或者它不适用于隐式转换? - Dykam
@Dykam:你假设T可以协变使用。我也不确定你所说的“this”是什么意思——但由于plainIX的类型是IX而不是X,我不认为原始代码可以直接运行。 - Jon Skeet
嗯,确实。那我漏掉了那部分。无论如何,隐式转换很快变得混乱。 - Dykam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接