如何创建一组相关属性?
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();
}
我有一个类型为 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();
}