c# - 将通用对象添加到列表时出现编译错误

标签 c# generics compiler-errors implicit-conversion

为什么 list.Add(new B())编译和list.Add(new Wrapper<B>())不编译?我认为要么两者都编译,要么都不编译,因为我认为编译器能够找出 B 的隐式转换。返回 Wrapper<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>());
    }
}

最佳答案

从您的问题看来,您认为添加 B 的实例到 Wrapper<A> 的列表工作是因为 B隐式转换为 Wrapper<B> ,以某种方式添加到列表中。然而,事实并非如此。事实上,编译器无法从 Wrapper<B> 进行转换。至 Wrapper<A>一步到位。

添加 B 实例的原因到 Wrapper<A> 的列表有效是因为编译器看到 B延伸A并且有一个来自 A 的用户定义的隐式转换至 Wrapper<A> .

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

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());
}

关于c# - 将通用对象添加到列表时出现编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16817548/

相关文章:

C# 通用接口(interface)

c - 错误: invalid type argument of '->' (have 'Personaggio' )

c++ - std::vector compiler error ld: symbol(s) not found for architecture x86_64

c# - 以下代码/设计是否存在并发问题

c# - 重复调用CurrentThread.ManagedThreadId或将值存储在线程本地存储中?

c# - 使用 HQL 查询从所有表而不是一个表中获取数据应该只获取 1 个表的数据

c# - 我可以将类型对象传递给泛型方法吗?

c# - 使用 RSACryptoServiceProvider 使用过期证书加密/解密数据没有错误

java - 如何在java中动态声明实例的泛型类型

linux - 编译 gcc 4.8.5