2

我的目标是 .Net 框架的 4.0 版。我写了以下简单的代码:

public class A
{
    public A()
    {
    }
}

public class B
{
    public B()
    {
    }

    public static implicit operator A(B b)
    {
        return new A();
    }
}

然后我创建了一个通用列表:

 var mylist = typeof(List<>).MakeGenericType(typeof(A)).GetConstructor(Type.EmptyTypes).Invoke(new object[]{});

B当我想添加以下代码的新实例时:

((IList<A>)mylist).Add(new B());

但是,如果我运行以下代码,则会引发以下异常:

The value "B" is not of type "A" and cannot be used in this generic collection.

参数名称:值

((IList)mylist).Add(new B());
4

2 回答 2

2

隐式转换仅在第一次发生,Add因为您将类型的对象添加BIList<A>. 在第二种情况下,您将其添加到 non-generic IList,这是一个对象集合,并且当对象实际添加到您的对象时,不会发生隐式转换和炸弹List<A>

即使这失败了:

var mylist = new List<A>();
((IList<A>)mylist).Add(new B());
((IList)mylist).Add(new B())

但是,您可以这样做:

((IList)mylist).Add((A)new B());
于 2013-01-19T19:59:52.523 回答
1

问题是当您将列表转换为IList<A>并调用Add时,编译器(隐式)将转换添加到您的B实例到A. 在第二种情况下,IList只接受方法object中的一个AddB是一个对象,所以它不会被强制转换为A. 因此,当方法试图在内部将其添加到底层数据结构时,它会引发异常。

您甚至可以通过以下代码对其进行测试:

var fails = (A) (object) new B();

由于您询问如何解决问题(尽管在这种情况下我没有看到将您的类型转换为的必要性IList),您可以在添加时显式地B转换您的类型A。例子:

mylist.Add((A) new B());
于 2013-01-19T19:57:47.723 回答