2

为什么list.Add(new B())编译list.Add(new Wrapper<B>())而不编译?我认为要么两者都编译,要么都不编译,因为我认为编译器能够找出B返回的隐式转换 aWrapper<B>new Wrapper<B>(). 我在 VS 2012 中使用 C# 4。

class Wrapper<T> where T : new()
{
    public static implicit operator Wrapper<T>(T obj)
    {
        return new Wrapper<T>();
    }
    public static implicit operator T(Wrapper<T> obj)
    {
        return new T();
    }
}
class A { }
class B : A { }
class MyClass
{
    public static void Main(string[] args)
    {
        List<Wrapper<A>> list = new List<Wrapper<A>>();
        //This line compiles and runs successfully
        list.Add(new B());
        //This line doesn't compile
        list.Add(new Wrapper<B>());
    }
}
4

2 回答 2

2

从您的问题看来,您认为将 的实例添加B到作品列表中,Wrapper<A>因为B被隐式转换为 a Wrapper<B>,它以某种方式添加到列表中。然而,这不是正在发生的事情。事实上,编译器不能一步 转换 from Wrapper<B>to 。Wrapper<A>

将 的 实例添加B到作品列表的原因Wrapper<A>是因为编译器看到了BextendsA并且存在用户定义的隐式转换 from Ato Wrapper<A>

您可能认为您也可以将 a 添加Wrapper<B>到列表中,Wrapper<A>因为有一个用户定义的隐式转换 from Wrapper<B>toBBextendsA并且有一个用户定义的隐式转换 from Ato Wrapper<A>但是,根据规范(此处详述第 6.4.4 节),您不能以这种方式将用户定义的隐式转换链接在一起。事实上,最小的例子甚至不需要处理泛型。考虑这个问题的简单示例:

class A 
{
    public static implicit operator B(A a) { return default(B); }
}
class B
{
    public static implicit operator C(B a) { return default(C); }
}
class C
{
    public static void Method(C c) { }
}
public static void Main()
{
    C.Method(new A());
}

当然,如果你明确地进行演员表,那么它的工作原理:

public static void Main()
{
    C.Method((B)new A());
}
于 2013-05-29T15:14:21.817 回答
-2

list.Add(new B());没有在列表添加新Wrapper<B>的。它正在向列表中添加一个新Wrapper<A>的。

编译器能够确定预期的类型是Wrapper<A>,并且存在从现有内容new B()到 a的隐式转换,Wrapper<A>因为 a 的操作数Wrapper<A>需要接受一个A对象,并且new B() A.

list.Add(new Wrapper<B>());不起作用,因为不允许将 a 添加Wrapper<B>到 aList<Wrapper<A>>因为List不是协变的。

于 2013-05-29T15:18:38.787 回答