我想实现相同的简单通用转换方法,但在运行时我遇到错误。
所以场景非常简单。我有相同的服务,返回外部类型的项目列表。我有自己的WrapperExternal类,它只是包装这个类并向它公开一些额外的功能。我有一些继承自WrapExternal的类,并添加了不同的功能。
我想创建接受外部列表项列表并返回指定类型项目列表的通用方法。
我的申请代码:
static void Main(string[] args)
{
var items = GetItemsFromServer();
var converted = ConvertItems<SubWrapperExternal>(items).ToList();
}
public static IEnumerable<T> ConvertItems<T>(IEnumerable<External> externalItems) where T : WrapperExternal
{
return externalItems
.Where( item => true)
.Select(item => (T)item);
}
当您尝试运行此代码时,您将在第(t)行项中获得异常:
An unhandled exception of type 'System.InvalidCastException' occurred in ConsoleApplication1.exe
Additional information:
Unable to cast object of type 'ConsoleApplication1.WrapperExternal' to type 'ConsoleApplication1.SubWrapperExternal'.
你知道我怎样才能让它发挥作用?
测试应用程序代码:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var items = GetItemsFromServer();
var converted = ConvertItems<SubWrapperExternal>(items).ToList();
}
private static List<External> GetItemsFromServer()
{
return new List<External>
{
new External{Name = "A"},
new External{Name = "B"},
new External{Name = "C"},
};
}
public static IEnumerable<T> ConvertItems<T>(IEnumerable<External> externalItems) where T : WrapperExternal
{
return externalItems
.Where( item => true)
.Select(item => (T)item);
}
}
class External
{
public string Name { get; set; }
}
class WrapperExternal
{
public External External { get; private set; }
public WrapperExternal(External external)
{
External = external;
}
public static explicit operator WrapperExternal(External item)
{
return item != null ? new WrapperExternal(item) : null;
}
public static implicit operator External(WrapperExternal item)
{
return item != null ? item.External : null;
}
}
class SubWrapperExternal : WrapperExternal
{
public SubWrapperExternal(External external)
: base(external)
{
}
public static explicit operator SubWrapperExternal(External item)
{
return item != null ? new SubWrapperExternal(item) : null;
}
public static implicit operator External(SubWrapperExternal item)
{
return item != null ? item.External : null;
}
}
}
答案 0 :(得分:2)
转换运算符非常适用于泛型 - 泛型不支持任何静态运算符重载。因此,(T)
演员正在执行非转换类型检查(泛型需要为每个可能的T
使用相同的IL,请记住) - 基本castclass
。
唯一的&#34;简单&#34;做你想做的事就是用dynamic
作弊:
return externalItems.Select(item => (T)(dynamic)item);
由于C#特定的dynamic
提供程序知道C#的所有通用规则,因此它知道转换运算符,并将按需应用它们。与此相关的性能成本略有下降,但它并不像第一眼看到的那样糟糕,因为每种类型的策略都被缓存(如IL) - 它不会执行每个项目的反射