【问题标题】:explicit conversion operator error when converting generic lists转换通用列表时出现显式转换运算符错误
【发布时间】:2010-12-30 15:00:25
【问题描述】:

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

用户定义的转换必须与封闭类型相互转换

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

感谢您的帮助。

【问题讨论】:

    标签: c# operators operator-overloading


    【解决方案1】:

    错误“用户定义的转换必须转换为封闭类型或从封闭类型转换”准确地说明了它的含义。如果你有一个转换运算符

    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&lt;Model.objA&gt;List&lt;Entity.objA&gt; 类中,但当然您不能这样做,因为您无权更改这些类型。

    您可以使用Enumerable.Select 投影到其他类型,或使用List&lt;T&gt;.ConvertAll。例如:

    public static class ListExtensions {
        public static List<Model.objA> ConvertToModel(this List<Entity.objA> entities) {
            return entities.ConvertAll(e => (Model.objA)e);
        }
    }
    

    【讨论】:

    • .ConvertAll ... 太棒了!
    【解决方案2】:

    基本上,你不能这样做。在您的运算符中,输入或输出类型必须是声明运算符的类型。一种选择可能是扩展方法,但老实说 LINQ Select 本身非常接近,List&lt;T&gt;.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()

    【讨论】:

      猜你喜欢
      • 2013-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多