不使用泛型将类A转换为类B
本文关键字:转换 泛型 | 更新日期: 2023-09-27 18:14:01
我有两个彼此没有连接的类:
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();
输出为:
附加信息:无法将类型"A"的对象强制转换为类型"B"。
有什么办法吗?
您可以使用Select()
代替这种方式:
List<B> addressListOther = addressList.Select(a => new B { Address = a.Address}).ToList();
或者您可以覆盖B
类中的explicit operator
:
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
这个异常的原因是,装箱值只能解装箱为与类型完全相同的变量。//
附加信息:
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)
。
它们不能相互继承,所以你不能这样做。Cast<T>
遍历集合,并尝试将元素强制转换为指定的类型。
如果你做以下事情,你将失败:
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();
另一种方法是在
A
类中重写implicit operator
:
public static implicit operator B(A a)
{
return new B { Address = a.Address };
}
然后下面的代码将word:
List<A> aList = new List<A> { new A { Address = "a" } };
List<B> bList = aList.Select(a => (B)a).ToList();
对我来说最简单的方法是引入一个超类。
public class ClassWithAddress
{
public string Address{get;set;}
}
然后你将从那个类中派生出每个类,并像这样删除address属性:
public class A : ClassWithAddress
{
}
public class B : ClassWithAddress
{
}
之后,你可以用超类ClassWithAddress
做关于地址属性的列表操作。