转换通用列表时显式转换运算符错误

时间:2009-12-28 22:38:18

标签: c# operators operator-overloading

我正在创建一个显式转换运算符,用于将通用实体类型列表转换为通用的模型类型列表。有谁知道为什么我会收到以下错误:

  

用户定义的转换必须转换为封闭类型

我已经在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;
    }

感谢您的帮助。

2 个答案:

答案 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()