使用接口的隐式转换操作符

68

我有一个通用类,我正在尝试实现隐式类型转换。虽然它大部分都可以工作,但对于接口转换却不起作用。进一步调查后,我发现存在编译器错误:“从接口的用户定义的转换”适用。虽然我理解在某些情况下应该强制执行这一点,但我所尝试的似乎是一个合法的案例。

以下是一个示例:

public class Foo<T> where T : IBar
{
    private readonly T instance;

    public Foo(T instance)
    {
        this.instance = instance;
    }
    public T Instance
    {
        get { return instance; }
    }
    public static implicit operator Foo<T>(T instance)
    {
        return new Foo<T>(instance);
    }
}

使用代码:

var concreteReferenceToBar = new ConcreteBar();
IBar intefaceReferenceToBar = concreteReferenceToBar;
Foo<ConcreteBar> concreteFooFromConcreteBar = concreteReferenceToBar;
Foo<IBar> fooFromConcreteBar = concreteReferenceToBar;
Foo<IBar> fooFromInterfaceBar = intefaceReferenceToBar; // doesn't work

有没有人知道解决方法,或者能够令我满意地解释为什么我不能将interfaceReferenceToBar隐式转换为Foo<IBar>,因为在我的情况下它并没有被转换,而只是包含在Foo中呢?

编辑: 看起来协变可能会提供救赎。希望C# 4.0规范允许使用协变隐式转换接口类型。

1个回答

75
您无法这样做的原因是因为在C#语言规范中明确禁止了这种行为: 来源:ECMA-334第15.10.4节 一个类或结构体允许声明从源类型S到目标类型T的转换,前提条件是以下所有条件都为真:
...
S和T均不是object或接口类型。
以及
不允许用户定义的转换从或到接口类型。特别地,此限制确保在向接口类型转换时不会发生用户定义的转换,并且仅当被转换的对象实际实现了指定的接口类型时,才能成功转换为接口类型。

2
我理解这是规范的一部分,接口的隐式转换在某些情况下应该是无效的,但所有情况下都是吗? - Michael Meadows
2
我同意你的观点,我也不知道为什么他们要在所有情况下都使其无效。在这种情况下,你可以在编译时确定强制转换是(应该是)有效的。 - Adam Hughes
3
认为隐式接口转换受到的限制与COM互操作的实现方式有关。COM使用QueryInterface,而.NET会自动处理它。允许隐式接口转换会干扰这个过程。 - Mark
6
@MichaelMeadows,你可能会对Adam Houldsworth和Eric Lippert在C# 4.0环境下与我的类似问题所做出的回答感到启发。请参考。 - gregsdennis
2
这个决定他们是否在任何地方解释了原因? - Hatchling

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