【问题标题】:Extension method on ObservableCollection<MyType>, MyType : IEnumerable<MyType>ObservableCollection<MyType>, MyType 上的扩展方法:IEnumerable<MyType>
【发布时间】:2018-08-24 00:18:09
【问题描述】:

我在 ObservableCollection 上为自定义类型创建扩展方法时遇到问题。我需要创建的扩展方法是“ToAnotherType”类型(如 ToList、ToArray)。 MyPoint 示例实现了 IEnumerable 接口,但我认为我没有正确公开 yield?

真实的事情显然有更多的事情发生,这只是控制台应用程序中的一个精简示例,用于识别问题。我尝试将 OC 更改为常规 List 以查看那里是否发生了某些事情,但事实并非如此。

我看到许多“如何使您的类可枚举”示例创建从 List 派生的第二个类(IE,公共类 MyPointList : List),但是当原始类型可以自己处理它或让它被推送时,这似乎很浪费在部分类文件中关闭。

这一切看起来都在工作,直到扩展方法本身中的 foreach - 我得到一个错误,说“MyPoint”不包含“X”和“Y”的定义。

我显然可以使用一个接收 List 并返回一个 List 的方法来处理转换,但如果有扩展名,那就太好了。

关于我如何完成我所做的代码的参考: https://www.codeproject.com/Articles/474678/A-Beginners-Tutorial-on-Implementing-IEnumerable-I

https://dotnetcodr.com/2015/07/24/implementing-an-enumerator-for-a-custom-object-in-net-c/

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Collections;

namespace EnumerableDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            var myPoints = new ObservableCollection<MyPoint>
            {
                new MyPoint(10, 10),
                new MyPoint(20, 20),
                new MyPoint(30, 30),
                new MyPoint(40, 40),
                new MyPoint(50, 50)
            };

            Console.WriteLine("Print a single point via extension method:");
            PrintSinglePointToConsole(myPoints[0].ToPoint());

            Console.WriteLine("");
            Console.WriteLine("Print the whole OC of points:");
            PrintPointsToConsole(myPoints.ToPoints());
            Console.ReadLine();
        }

        public static void PrintSinglePointToConsole(Point point)
        {
            Console.WriteLine("Point {0},{1}", point.X, point.Y);
        }

        public static void PrintPointsToConsole(List<Point> points)
        {
            foreach (var item in points)
            {
                Console.WriteLine("Point: {0},{1}", item.X, item.Y);
            }
        }

    }

    public class MyPoint : IEnumerable<MyPoint>
    {
        private List<MyPoint> _myPoints = new List<MyPoint>();

        private int _x { get; set; } = 0;
        public int X { get { return _x; } set { _x = value; } }

        private int _y { get; set; } = 0;
        public int Y { get { return _y; } set { _y = value; } }

        public MyPoint()
        {
        }

        public MyPoint(int x, int y)
        {
            _x = x;
            _y = y;
        }

        public IEnumerator<MyPoint> GetEnumerator()
        {
            foreach (var item in _myPoints)
            {
                yield return item;
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }

    public static class MyPointExtension
    {
        public static Point ToPoint(this MyPoint point)
        {
            return new Point(point.X, point.Y);
        }

        public static List<Point> ToPoints<MyPoint>(this ObservableCollection<MyPoint> list)
        {
            var result = new List<Point>();

            foreach (var item in list)
            {
                //Line with error: 
                //'MyPoint' Does not contain a definition for 'X' and no extension method for
                //'X' accepting a first argument type of 'MyPoint' could be found.
                result.Add(new Point(item.X, item.Y));
            }

            return result;
        }
    }
}

【问题讨论】:

    标签: c#


    【解决方案1】:

    ToPoints 中不需要 MyPoint 泛型参数。

    随便用

    public static List<Point> ToPoints(this ObservableCollection<MyPoint> list)
    

    结果是:

    Print a single point via extension method:
    Point 10,10
    
    Print the whole OC of points:
    Point: 10,10
    Point: 20,20
    Point: 30,30
    Point: 40,40
    Point: 50,50
    

    顺便说一句,如果您丢弃 _x 和 _y 字段,您还可以使代码更简洁更短,如下所示:

    public int X { get; set; } = 0;
    public int Y { get; set; } = 0;
    
    public MyPoint(int x, int y)
    {
        X = x;
        Y = y;
    }
    

    【讨论】:

    • 谢谢 - 谁知道删除 9 个字符会解决几个小时的烦恼。 MyPoint 类确实包含 DependencyProperties,因此后备存储可以确保 GetValue 和 SetValue 过程被模仿。但是,是的,我可以在变量声明中将 _x 和 _y 的默认值设置为 = 0 并删除 { get;放; } 用于示例应用程序。
    • 实际上,FWIW 从 MyPoints 类中删除整个 IEnumerable 接口不会更改输出。唯一的问题实际上是方法签名。
    【解决方案2】:

    最终的代码块,它使用了另一个扩展方法 ToPoint

    public static List<Point> ToPoints(this ObservableCollection<MyPoint> list)
    {
        var result = new List<Point>();
    
        foreach (var item in list)
        {
            result.Add(item.ToPoint());
        }
    
        return result;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-27
      • 2012-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-05
      • 1970-01-01
      相关资源
      最近更新 更多