如何对列表进行类型划分?

时间:2010-10-27 10:06:12

标签: c# .net

我在第三方DLL中有一个类。

Class A
{

}

我需要装饰它,所以我创建了它的本地实例并使用它

class B
{

}

DLL包含一个函数,它给出了A的列表。但是如果我尝试使用它如下

B listofB = Dll.FindAllA()

我收到错误无法将DLL.A隐式转换为Proj.B

这两个类的结构没有区别。我该如何转换它?

4 个答案:

答案 0 :(得分:5)

如果AB没有任何共同之处(除了看起来相同),编译器就不走运了。选项:

  • 继承(有时)
  • 将转换运算符添加到任一类型
  • 如果类型不在您的控件中,则添加ToA等扩展方法
  • 尝试使用automapper
  • 使用序列化(有一些方法可以使一些序列化程序使用不同的名称等)

我会首先选择前两个选项。请注意,使用List<T>,您可以使用全部转换,即:

List<A> orig = ...
List<B> copy = orig.ConvertAll(a => (B)a);// assumes a conversion operator exists

对于其他类型,LINQ Select方法等同于ConvertAll

答案 1 :(得分:1)

我认为你自己部分给出了答案,因为你在谈论'装饰'。以装饰A的方式实现BB的后代,并在B的实例中包装返回集合的元素:

public class B
{
    // Methods of B
}

public class AToBAdapter : B
{
    A a;

    public AToBAdapter(A a)
    {
        this.a = a;
    }

    // Override methods of B to map to A
}

现在有了这个适配器,您可以更改As到Bs的列表:

B[] listofB = Dll.FindAllA().Select(a => new AToBAdapter(a) as B).ToArray();

答案 2 :(得分:1)

你可以在B类上重载强制转换操作符:

public static implicit operator B(A e)
{
    return new B(e.Property1, e.Property2);
}
顺便说一句,你应该只使用隐式,如果没有数据丢失而且你不期望异常,否则改为显式:(B)A

答案 3 :(得分:0)

C#是协变的,不支持隐式转换集合。虽然这个问题已经在C#4.0中以稍微不同的方式解决了。例如,以下代码将引发编译时异常

  public class A
  {

  }
   public class B : A
   {

   }

   List<B> obj1 = new List<B>();
   List<A> obj2 = obj1;

虽然B是从A派生的,但隐式转换不会发生。它必须如下所示明确转换。

   List<A> obj2 = obj1.ConvertAll(b => (A)b);