我正在创建一个显式转换运算符,用于将通用实体类型列表转换为通用的模型类型列表。有谁知道为什么我会收到以下错误:
用户定义的转换必须转换为封闭类型
我已经在Entity.objA和Model.objA之间有一个显式转换运算符,它运行正常。尝试转换通用列表时出现问题。这甚至可能吗?
这是我的代码:
public static explicit operator List<Model.objA>(List<Entity.objA> entities)
{
List<Model.objA> objs= new List<Model.objA>();
foreach (Entity.objA entity in entities)
{
objs.Add((Model.objA)entity);
}
return claims;
}
感谢您的帮助。
答案 0 :(得分:21)
错误“用户定义的转换必须转换为封闭类型或从封闭类型转换”确切地说明了它的含义。如果您有转换运算符
class MyClass {
public static explicit operator xxx(string s) { // details }
public static implicit operator string(xxx x) { // details }
}
然后xxx
必须是MyClass
。这就是“转换必须转换为封闭类型或从封闭类型转换”的含义。这里的封闭类型是MyClass
。
ECMA334 C#规范的相关部分是17.9.4:
转换运算符从源类型(由转换运算符的参数类型指示)转换为目标类型,由转换运算符的返回类型指示。只有当以下所有条件都为真时,才允许类或结构声明从源类型S到目标类型T的转换,其中S0和T0是从删除尾部得到的类型?来自S和T的修饰符(如果有):
S0和T0是不同的类型。
S0或T0是发生运算符声明的类或结构类型。
S0和T0都不是接口类型。
不包括用户定义的转换,从S到T或从T到S不存在转换。
所以这是你的代码:
public static explicit operator List<Model.objA>(List<Entity.objA> entities) {
List<Model.objA> objs= new List<Model.objA>();
foreach (Entity.objA entity in entities) {
objs.Add((Model.objA)entity);
}
return claims;
}
问题在于,要将其定义为转化运算符,它必须位于List<Model.objA>
或List<Entity.objA>
类中,但当然您不能这样做,因为您无权更改那些类型。
您可以使用Enumerable.Select
投射到其他类型,或List<T>.ConvertAll
。例如:
public static class ListExtensions {
public static List<Model.objA> ConvertToModel(this List<Entity.objA> entities) {
return entities.ConvertAll(e => (Model.objA)e);
}
}
答案 1 :(得分:2)
基本上,你不能这样做。在您的运算符中,输入或输出类型必须是声明运算符的类型。一个选项可能是扩展方法,但说实话,LINQ Select
本身非常接近,List<T>.ConvertAll
也是如此。
作为扩展方法方法的一个例子:
public static class MyListUtils {
public static List<Model.objA> ToModel(this List<Entity.objA> entities)
{
return entities.ConvertAll(entity => (Model.objA)entity);
}
}
或更一般地使用LINQ Select
:
public static class MyListUtils {
public static IEnumerable<Model.objA> ToModel(
this IEnumerable<Entity.objA> entities)
{
return entities.Select(entity => (Model.objA)entity);
}
}
并使用someList.ToModel()
。