如何创建一组相关属性?

How to create set of related properties?

我有一个类型为 Foo

的集合 foos

每个Foo都有一个属性Position

A Position 是结构保持坐标

struct Position
{
    Position(int x, int y, int z)
    {
        X = x;
        Y = y;
        Z = z;
    }

    int X { get; private set; }
    int Y { get; private set; }
    int Z { get; private set; }
}

我有一堆作用于 X、Y 或 Z 的方法。

void DoX(int whichX)
{
    var set = foos.Where(p => p.X == whichX);
    //..lots of code
}

void DoY(int whichY)
{
    var set = foos.Where(p => p.Y == whichY);
    //..lots of repeating code
}

那段代码叫我重构! 我想做的是:

void Do(int which, something theDimension)
{
    var set = foos.Where(p => p.[how to get X/Y/Z] == which);
    //..lots of non-repeating code
}

我通过添加一个枚举解决了它Dimensions

enum Dimensions
{
    X,
    Y,
    Z
}

并在 Position 上添加一个 Dimension 方法:

int Dimension(Dimensions d)
{
    switch (d)
    {
        case Dimensions.X:
            return X;
        case Dimensions.Y:
            return Y;
        case Dimensions.Z:
            return Z;
        default:
            throw new ArgumentException("Invalid argument");    
    }           
}

所以现在我可以这样调用 Do

void Do(int which, Dimensions d)
{
    var set = foos.Where(p => p.Dimension(d) == which);
    // .. stuff ..
}

但是,这似乎是一种非常人为的处理方式。根据经验,我知道我的代码最终总是使事情变得比需要的更复杂。我的问题是:如何简化?

根据大局,可能有更好的方法,但另一种方法可能会更快一些...

public void Do(Func<Position, int> dimension)
        {
            foos.Where(p => dimension(p) > 0).ToList();
        }

然后在你的位置上

    public static int FX(Position p) => p.X;
    public static int FY(Position p) => p.Y;
    public static int FZ(Position p) => p.Z;

然后做

  Do(Position.FX);

或者在 Position 上没有预先完成的功能你可以做...

Do(p => p.X);

或者完全另一种方式....(没有范围检查,但你可以添加它)

struct Position
{
    private int[] _values;
    Position(int x, int y, int z)
    {
        _values = new []{x, y, z};
    }
    public int X => _values[0]; 
    public int Y => _values[1]; 
    public int Z => _values[2];
    public int this[int dimension] => _values[dimension];
}

然后

 public void Do(int d)
        {
            foos.Where(p => p[d] > 0).ToList();
        }