【问题标题】:Advice to get rid of repeating if statement in my class在我的课堂上摆脱重复 if 语句的建议
【发布时间】:2021-12-02 18:31:48
【问题描述】:

我最近在工作中遇到了一段代码,它有一个重复的 if-else 条件,它检查一个名为 OperationType 的枚举:

public enum OperationType
{ A, B }

现在该类的工作是在设备 A 或设备 B 上运行操作,同时从 SharedDevice 读取数据并存储一些基本用于 X、Y 绘图的值。我们在DeviceA或DeviceB的函数中记录了SharedDevice的特性。问题是我们需要遍历不同参数的列表并将它们发送到 SharedDevice。此列表对于设备 A 和设备 B 是不同的。

Device类:

public class Device
{
    public double CurrentValue { get; }
    public DeviceParameters Parameters { get; set; }
}

这里是负责执行这个操作的类:

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 逻辑?

【问题讨论】:

  • 您可以从一个将List&lt;double&gt; 作为参数和List&lt;DeviceParameters&gt; 并传入XValuesOfBXValuesOfB 等的方法开始。基于operationType 。小步骤重构..

标签: c# if-statement design-patterns enums


【解决方案1】:

一种相当简单的方法是声明一个表示 A 或 B 的变量:

var XValues = operationType == OperationType.A ? XValuesOfA : XValuesOfB;

那么你可以只使用 XValues。对DeviceA 执行相同操作。如果您有更多操作,您可以使用switch expression

更简洁的解决方案是制作包含 A 或 B 所需的所有内容的单独对象,这样您的类就可以简单地检查操作类型,然后将所有工作委托给相应的对象。即

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。我发现这更容易使用,并且有助于避免重复代码。

【讨论】:

【解决方案2】:

在不改变类字段/属性的情况下,我会使用新方法:

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);
}

【讨论】:

    【解决方案3】:

    您应该添加新课程。这将用于定义设备类型特定的属性。

    这样的类;

    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();
    }
    

    这是您粘贴的整个代码的重构版本:

    https://dotnetfiddle.net/dLyJl9

    【讨论】:

      猜你喜欢
      • 2020-07-05
      • 1970-01-01
      • 1970-01-01
      • 2022-11-23
      • 2016-11-23
      • 1970-01-01
      • 2020-08-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多