在我的 class 中摆脱重复 if 语句的建议
Advice to get rid of repeating if statement in my class
我最近在工作中遇到一段代码,它有一个重复的 if-else
条件,用于检查名为 OperationType
的枚举:
public enum OperationType
{ A, B }
现在 class 的工作是 运行 在设备 A 或设备 B 上进行操作,同时从 SharedDevice
读取并存储一些值,基本上用于X,Y 图。我们在DeviceA或DeviceB的函数中记录SharedDevice的特性。问题是我们需要遍历不同参数的列表并将它们发送到 SharedDevice。此列表对于设备 A 和设备 B 是不同的。
Device
class:
public class Device
{
public double CurrentValue { get; }
public DeviceParameters Parameters { get; set; }
}
这里是负责执行此操作的class:
public class MyOperationExecuter
{
public Device SharedDevice { get; }
public Device DeviceA { get; }
public Device DeviceB { get; }
public List<DeviceParameters> ParametersA { get; }
public List<DeviceParameters> ParametersB { get; }
public List<double> XValuesOfA { get; }
public List<double> YValuesOfA { get; }
public List<double> XValuesOfB { get; }
public List<double> YValuesOfB { get; }
public void DoMyOperation(OperationType operationType)
{
List<DeviceParameters> changingDeviceParameters;
if (operationType == OperationType.A)
{
changingDeviceParameters = ParametersA;
}
else
{
changingDeviceParameters = ParametersB;
}
if (operationType == OperationType.A)
{
XValuesOfA.Clear();
YValuesOfA.Clear();
}
else
{
XValuesOfB.Clear();
YValuesOfB.Clear();
}
foreach (var parameters in changingDeviceParameters)
{
// set the device parameters
SharedDevice.Parameters = parameters;
// retrieve the device readings and store the values in the correct dataprovider
if (operationType == OperationType.A)
{
XValuesOfA.Add(DeviceA.CurrentValue);
YValuesOfA.Add(SharedDevice.CurrentValue));
}
else
{
XValuesOfB.Add(DeviceB.CurrentValue);
YValuesOfB.Add(SharedDevice.CurrentValue);
}
}
// save updated x,y data
Save();
}
}
如您所见,有一个重复的 if 语句,这不是未来的证据,因为我们必须在每一步中检查枚举。此外,我们可能需要添加一个 C 型设备,这将导致不断增长的 switch 语句。我们可能还需要对 A 和 B 执行操作。我应该如何重构这个操作,以便我可以继续扩展它,而不必总是重复 if-else 逻辑?
一个相当简单的方法是声明一个代表 A 或 B 的变量:
var XValues = operationType == OperationType.A ? XValuesOfA : XValuesOfB;
那么你就可以使用 XValues 了。对 DeviceA
执行相同的操作。如果你有更多的操作,你可以使用 switch expression.
一个更简洁的解决方案是制作包含 A 或 B 所需的所有内容的单独对象,这样您的 class 可以简单地检查操作类型,然后将所有工作委托给相应的对象。即
public class MyDevice
{
public Device SharedDevice { get; }
public Device Device { get; }
public List<DeviceParameters> Parameters { get; }
public List<double> XValuesOf { get; }
public List<double> YValuesOf { get; }
public void DoMyOperation()
{
...
}
}
我还建议使用包含 X 和 Y 值的单个列表,例如 Vector2。我发现这更容易使用,并且有助于避免重复代码。
您应该添加新的 class。这将用于定义设备类型特定的属性。
一个class这样的;
public class MyDeviceValues
{
public MyDeviceValues(List<DeviceParameters> parameters, List<double> xValuesOf, List<double> yValuesOf)
{
Parameters = parameters;
XValues = xValuesOf;
YValues = yValuesOf;
}
public List<DeviceParameters> Parameters { get; }
public List<double> XValues { get; }
public List<double> YValues { get; }
}
因此,您可以拥有一个通用的 DoMyOperation
函数。它将是这样的:
public void DoMyOperation(MyDeviceValues myDeviceValues)
{
var changingDeviceParameters = myDeviceValues.Parameters;
myDeviceValues.XValues.Clear();
myDeviceValues.YValues.Clear();
foreach (var parameters in changingDeviceParameters)
{
// set the device parameters
SharedDevice.Parameters = parameters;
// retrieve the device readings and store the values in the correct dataprovider
myDeviceValues.XValues.Add(DeviceA.CurrentValue);
myDeviceValues.YValues.Add(SharedDevice.CurrentValue);
}
// save updated x,y data
Save();
}
这是您粘贴的整个代码的重构版本:
不改变 class fields/properties 我会采用新方法:
private void SetParameters(List<DeviceParameters> parameters, List<double> xValues, List<double> yValues, Device device)
{
xValues.Clear();
yValues.Clear();
foreach(var parameter in parameters)
{
SharedDevice.Parameters = parameter;
xValues.Add(device.CurrentValue);
yValues.Add(SharedDevice.CurrentValue);
}
}
然后在 DoMyOperation 中足以:
if (operationType == OperationType.A)
{
SetParameter(ParametersA, XValuesOfA, YValuesOfA, DeviceA);
}
else
{
SetParameter(ParametersB, XValuesOfB, YValuesOfB, DeviceB);
}
我最近在工作中遇到一段代码,它有一个重复的 if-else
条件,用于检查名为 OperationType
的枚举:
public enum OperationType
{ A, B }
现在 class 的工作是 运行 在设备 A 或设备 B 上进行操作,同时从 SharedDevice
读取并存储一些值,基本上用于X,Y 图。我们在DeviceA或DeviceB的函数中记录SharedDevice的特性。问题是我们需要遍历不同参数的列表并将它们发送到 SharedDevice。此列表对于设备 A 和设备 B 是不同的。
Device
class:
public class Device
{
public double CurrentValue { get; }
public DeviceParameters Parameters { get; set; }
}
这里是负责执行此操作的class:
public class MyOperationExecuter
{
public Device SharedDevice { get; }
public Device DeviceA { get; }
public Device DeviceB { get; }
public List<DeviceParameters> ParametersA { get; }
public List<DeviceParameters> ParametersB { get; }
public List<double> XValuesOfA { get; }
public List<double> YValuesOfA { get; }
public List<double> XValuesOfB { get; }
public List<double> YValuesOfB { get; }
public void DoMyOperation(OperationType operationType)
{
List<DeviceParameters> changingDeviceParameters;
if (operationType == OperationType.A)
{
changingDeviceParameters = ParametersA;
}
else
{
changingDeviceParameters = ParametersB;
}
if (operationType == OperationType.A)
{
XValuesOfA.Clear();
YValuesOfA.Clear();
}
else
{
XValuesOfB.Clear();
YValuesOfB.Clear();
}
foreach (var parameters in changingDeviceParameters)
{
// set the device parameters
SharedDevice.Parameters = parameters;
// retrieve the device readings and store the values in the correct dataprovider
if (operationType == OperationType.A)
{
XValuesOfA.Add(DeviceA.CurrentValue);
YValuesOfA.Add(SharedDevice.CurrentValue));
}
else
{
XValuesOfB.Add(DeviceB.CurrentValue);
YValuesOfB.Add(SharedDevice.CurrentValue);
}
}
// save updated x,y data
Save();
}
}
如您所见,有一个重复的 if 语句,这不是未来的证据,因为我们必须在每一步中检查枚举。此外,我们可能需要添加一个 C 型设备,这将导致不断增长的 switch 语句。我们可能还需要对 A 和 B 执行操作。我应该如何重构这个操作,以便我可以继续扩展它,而不必总是重复 if-else 逻辑?
一个相当简单的方法是声明一个代表 A 或 B 的变量:
var XValues = operationType == OperationType.A ? XValuesOfA : XValuesOfB;
那么你就可以使用 XValues 了。对 DeviceA
执行相同的操作。如果你有更多的操作,你可以使用 switch expression.
一个更简洁的解决方案是制作包含 A 或 B 所需的所有内容的单独对象,这样您的 class 可以简单地检查操作类型,然后将所有工作委托给相应的对象。即
public class MyDevice
{
public Device SharedDevice { get; }
public Device Device { get; }
public List<DeviceParameters> Parameters { get; }
public List<double> XValuesOf { get; }
public List<double> YValuesOf { get; }
public void DoMyOperation()
{
...
}
}
我还建议使用包含 X 和 Y 值的单个列表,例如 Vector2。我发现这更容易使用,并且有助于避免重复代码。
您应该添加新的 class。这将用于定义设备类型特定的属性。
一个class这样的;
public class MyDeviceValues
{
public MyDeviceValues(List<DeviceParameters> parameters, List<double> xValuesOf, List<double> yValuesOf)
{
Parameters = parameters;
XValues = xValuesOf;
YValues = yValuesOf;
}
public List<DeviceParameters> Parameters { get; }
public List<double> XValues { get; }
public List<double> YValues { get; }
}
因此,您可以拥有一个通用的 DoMyOperation
函数。它将是这样的:
public void DoMyOperation(MyDeviceValues myDeviceValues)
{
var changingDeviceParameters = myDeviceValues.Parameters;
myDeviceValues.XValues.Clear();
myDeviceValues.YValues.Clear();
foreach (var parameters in changingDeviceParameters)
{
// set the device parameters
SharedDevice.Parameters = parameters;
// retrieve the device readings and store the values in the correct dataprovider
myDeviceValues.XValues.Add(DeviceA.CurrentValue);
myDeviceValues.YValues.Add(SharedDevice.CurrentValue);
}
// save updated x,y data
Save();
}
这是您粘贴的整个代码的重构版本:
不改变 class fields/properties 我会采用新方法:
private void SetParameters(List<DeviceParameters> parameters, List<double> xValues, List<double> yValues, Device device)
{
xValues.Clear();
yValues.Clear();
foreach(var parameter in parameters)
{
SharedDevice.Parameters = parameter;
xValues.Add(device.CurrentValue);
yValues.Add(SharedDevice.CurrentValue);
}
}
然后在 DoMyOperation 中足以:
if (operationType == OperationType.A)
{
SetParameter(ParametersA, XValuesOfA, YValuesOfA, DeviceA);
}
else
{
SetParameter(ParametersB, XValuesOfB, YValuesOfB, DeviceB);
}