考虑此多边形结构最多可存储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
在PolygonEnumerator
中定义Polygon
类,这样它就可以访问xPoints
和yPoints
,那么您无需复制任何内容即可实现它:
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
}
}