2010-03-26 108 views
4

背景:

让我们假设我有下面的类:为什么C#中的隐式类型转换失败?

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类型的任何内容指定给它。编译器会报错以下错误:

Compiler error CS0266: Cannot implicitly convert type 'IX' to 'Wrapped<IX>'. An explicit onversion exists (are you missing a cast?)

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

+0

compilable if if replace“IX plainIX = new X();”用“X plainIX = new X();” – Nagg 2010-03-26 19:29:01

+0

@Nagg:因为我想实现的目标(即在现有的* COM库*上设计一个流畅的接口),所以对接口进行编程是绝对必要的。因此,不幸的是,你的建议不是一个可行的选择。 – stakx 2010-03-26 19:42:30

回答

5

我相信这是因为IX是一个接口。编译器认为,IX类型的值可能已经从Wrapped<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)) 

基本上转换可以是一个有点棘手因各种原因 - 简单方法通常更容易理解,国际海事组织。

+0

当'T'用'out'正确装饰,或者它不适用于隐式投射时,这将与C#4一起使用? – Dykam 2010-03-26 19:31:34

+0

@Dykam:你假设'T' *可以被共同使用。我也不确定你的意思是“这个” - 但是因为''plainIX'的类型是'IX'而不是'X',所以我不相信原始代码可以开箱即用。 – 2010-03-26 19:39:32

+0

嗯,的确如此。然后我错过了那部分。在任何情况下,隐式转换都会变得很麻烦。 – Dykam 2010-03-26 20:17:24