2013-01-19 40 views
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()); 
+1

什么是你的问题? –

+0

我该如何解决这个问题? –

回答

2

的隐式转换的发生仅在第一Add作为要添加B类型的对象到IList<A>。在第二种情况下,将其添加到非通用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()); 
+0

Thanks.But我写这个代码进行测试。在真正的代码中,我通过反射得到所有类型,并且我不能写入Add((A)new B()); –

1

的问题是,当你投你的列表IList<A>并调用Add,编译器(隐含)将强制转换为您B实例A。在第二种情况下,IList仅接受Add方法中的objectB是一个对象,所以它不会投射到A。因此,当该方法尝试将其内部添加到基础数据结构时,会引发异常。

你甚至可以通过这个代码测试:

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

既然你问到如何解决这个问题(虽然我不认为在这种情况下您铸造类型IList的必要性),你可以只是在添加时将你的B明确地转换为A。例如:

mylist.Add((A) new B()); 
+0

Thanks.But我写这个代码进行测试。在真正的代码中,我通过反射得到所有类型,并且我不能写入Add((A)new B()); –

+0

@afshinalizadeh我明白了。 – Mir