Cast class A to class B without generics

牧云@^-^@ 提交于 2019-12-13 10:11:18

问题


I have two classes that have no connection to one another :

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

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

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

When I do

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

the output is :

Additional information: Unable to cast object of type 'A' to type 'B'.

Any idea how to fix that ?


回答1:


You can use Select() instead of that way:

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

Or you can override explicit operator in class B:

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

And, then:

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

The reason of this exception:

Cast will throw InvalidCastException, because it tries to convert A to object, then cast it to B:

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

The reason of this exception is, a boxed value can only be unboxed to a variable of the exact same type.


Additional Information:

Here is the implemetation of the Cast<TResult>(this IEnumerable source) method, if you interested:

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

As you see, it returns CastIterator:

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

Look at the above code. It will iterate over source with foreach loop, and converts all items to object, then to (TResult).




回答2:


They do not inherit from each other so you can't do that. The Cast<T> iterates over the collection and tries to cast the items to the specified type.

If you do the following you will fail to0:

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

Instead use Select to project new B items.

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

Another way is to override the implicit operator in class A:

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

And then the followingcode will word:

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



回答3:


The simpliest way for me is to introduce a superclass.

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

Then you'll derive every class from that class and delete the address property like this:

public class A : ClassWithAddress
{
}
public class B : ClassWithAddress
{
}

After that you can do your list operations concerning the Address Property with the superclass ClassWithAddress.



来源:https://stackoverflow.com/questions/40148491/cast-class-a-to-class-b-without-generics

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!