将A类转换为B类而不使用泛型

时间:2016-10-20 07:50:32

标签: c# .net linq casting

我有两个彼此没有联系的类:

public class A
{
   public String Address {get;set}
}

public class B 
{
   public String Address {get;set}
}

List<A> addressList = DB.Addresses.GetAll();

当我这样做时

List<B> addressListOther = addressList.Cast<B>().ToList();

输出是:

  

附加信息:无法投射类型&#39; A&#39;输入&#39; B&#39;。

知道如何解决这个问题吗?

3 个答案:

答案 0 :(得分:7)

您可以使用Select()代替:

List<B> addressListOther = addressList.Select(a => new B { Address = a.Address}).ToList();

或者您可以在课程explicit operator中覆盖B

public static explicit operator B(A a)  // explicit A to B conversion operator
{
    return new B { Address = a.Address };
}

然后:

List<B> addressListOther = aList.Select(a => (B)a).ToList();

此异常的原因:

Cast会抛出InvalidCastException,因为它会尝试将A转换为object,然后将其转换为B

A myA = ...;
object myObject = myA ;
B myB= (B)myObject; // Exception will be thrown here

此异常的原因是, 盒装值 只能取消装入 完全相同类型 <的变量/ strong>即可。


其他信息:

以下是Cast<TResult>(this IEnumerable source)方法的实现,如果您感兴趣:

public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) {
    IEnumerable<TResult> typedSource = source as IEnumerable<TResult>;
    if (typedSource != null) return typedSource;
    if (source == null) throw Error.ArgumentNull("source");
    return CastIterator<TResult>(source);
}

如您所见,它返回CastIterator

static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source) {
    foreach (object obj in source) yield return (TResult)obj;
}

看看上面的代码。它将使用foreach循环遍历源代码,并将所有项目转换为object,然后转换为(TResult)

答案 1 :(得分:4)

他们不会相互继承,所以你不能这样做。 Cast<T>遍历集合并尝试将项目转换为指定的类型。

如果您执行以下操作,则无法执行0:

A a = new A { Address = "a"};
B b = (B)a; // Compile error of: Cannot convert type A to B

而是使用Select来投放新的B项。

List<B> addressListOther = addressList.Select(a => new B { Address = a.Address}).ToList();

另一种方法是覆盖班级implicit operator中的A

public static implicit operator B(A a)
{
    return new B { Address = a.Address };
}

然后以下代码将说出:

List<A> aList = new List<A> { new A { Address = "a" } };
List<B> bList = aList.Select(a => (B)a).ToList();

答案 2 :(得分:1)

对我来说,最简单的方法是引入一个超类。

https://JENKSIN_URL/api/json?tree=jobs[name,color,buildable,healthReport[description,score,iconUrl],builds[changeSet[items[msg,user]]]]

然后你将从该类派生每个类并删除地址属性,如下所示:

public class ClassWithAddress
{
    public string Address{get;set;}
}

之后,您可以使用超类public class A : ClassWithAddress { } public class B : ClassWithAddress { } 执行与地址属性相关的列表操作。