实现IEnumerator 对于固定数组

问题描述 投票:0回答:1

考虑此多边形结构最多可存储64个索引点和可枚举点:

public unsafe struct Polygon : IEnumerable<System.Drawing.PointF>
{
    private int points;
    private fixed float xPoints[64];
    private fixed float yPoints[64];

    public PointF this[int i] => return new PointF(xPoints[i], yPoints[i]);

    public IEnumerator<PointF> GetEnumerator()
    {
        return new PolygonEnumerator(ref this);
    }
}

我要求必须按值复制Polygon,因此它是struct。(理论上:修改副本不会对原件产生副作用。]

我也希望它实现IEnumerable<PointF>。(理论上:能够写for (PointF p in poly)

据我所知,C#不允许您覆盖值类型的复制/分配行为。如果可能的话,那么有“低垂的果实”将回答我的问题。

我实现Polygon的按值复制行为的方法是使用unsafe和固定数组,以允许多边形在结构本身中存储多达64个点,这可以防止通过以下方式间接修改多边形它的副本。

虽然我要实施PolygonEnumerator : IEnumerator<PointF>时遇到问题。另一个要求(wishful think)是枚举器将返回与PointF的固定数组匹配的Polygon值,即使这些点在迭代过程中被修改了也是如此。(Rationale:遍历数组的工作原理是这样的,因此此多边形的行为应符合用户的期望。]]]

public class PolygonEnumerator : IEnumerator<PointF>
{
    private int position = -1;

    private ??? poly;

    public PolygonEnumerator(ref Polygon p)
    {
        // I know I need the ref keyword to ensure that the Polygon
        // passed into the constructor is not a copy
        // However, the class can't have a struct reference as a field

        poly = ???;
    }

    public PointF Current => poly[position]; 

    // the rest of the IEnumerator implementation seems straightforward to me

}

根据我的要求我可以做什么来实现PolygonEnumerator类?

在我看来,我无法存储对原始多边形的引用,因此我必须将其点的副本复制到枚举器本身;但这意味着枚举器无法访问对原始多边形所做的更改!

我完全可以接受“这是不可能的”答案。

也许我在这里为自己挖了一个空洞,却错过了有用的语言功能或原始问题的常规解决方案。

考虑此多边形结构,该结构最多可存储64个索引点和可枚举点:公共不安全结构多边形:IEnumerable {私人固定...

c# fixed unsafe ienumerator
1个回答
0
投票

PolygonEnumerator中定义Polygon类,这样它就可以访问xPointsyPoints,那么您无需复制任何内容即可实现它:

public unsafe struct Polygon : IEnumerable<System.Drawing.PointF>
{
    private int points;
    private fixed float xPoints[64];
    private fixed float yPoints[64];

    public PointF this[int i] => new PointF(xPoints[i], yPoints[i]);

    public IEnumerator<PointF> GetEnumerator()
    {
        return new PolygonEnumerator(ref this);
    }

    public class PolygonEnumerator : IEnumerator<PointF>
    {
        private int position = -1;

        private float[] xPoints;
        private float[] yPoints;

        public PolygonEnumerator(ref Polygon p)
        {
            xPoints = p.xPoints;
            yPoints = p.yPoints;
        }

        public PointF Current => new PointF(xPoints[position], yPoints[position]);

        // the rest of the IEnumerator implementation seems straightforward to me
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.