避免代码重复 c#

Avoid code repeating c#

目前正在为万用表制作库,此时我发现自己在重复自己。我在问,如何连接这两个功能。这只是开始,我将有更多类似的功能,我只需要某种示例,或修复此特定代码,然后我就能自己弄清楚其他人。

public string MeasureVoltage()
{
    string Meas = "MEAS:VOLT:";
    if (vt == VoltageType.DC)
    {
       Meas += "DC?";
    }
    else
    {
       Meas += "AC?";
    }
    io.PrintfAndFlush(Meas + "\n");
    Console.WriteLine(Meas);
    string response;
    io.Scanf("%s", out response);
    return response;
}

public string MeasureCurrent()
{
    string Meas = "MEAS:CURR:";
    if (ct == CurrentType.DC)
    {
       Meas += "DC?";
    }
    else
    {
       Meas += "AC?";
    }
    io.PrintfAndFlush(Meas + "\n");
    Console.WriteLine(Meas);
    string response;
    io.Scanf("%s", out response);
    return response;
}

public enum VoltageType { AC, DC }
public enum CurrentType { AC, DC }

我猜你可以制作一个 Measure 方法,并给出一个你想要它测量的参数,然后只对你当前方法之间不同的东西使用 switch 语句

我会放

io.PrintfAndFlush(Meas + "\n");
Console.WriteLine(Meas);
string response;
io.Scanf("%s", out response);
return response;

在它自己的方法中并从两者调用它:

public string MeasureVoltage()
{
    string Meas = "MEAS:VOLT:";
    if (vt == VoltageType.DC)
    {
        Meas += "DC?";
    }
    else
    {
        Meas += "AC?";
    }
    return PerformMeasurement(Meas);
}

public string MeasureCurrent()
{
    string Meas = "MEAS:CURR:";
    if (ct == CurrentType.DC)
    {
        Meas += "DC?";
    }
    else
    {
        Meas += "AC?";
    }
    return PerformMeasurement(Meas);
}

private string PerformMeasurement(string Meas)
{
    io.PrintfAndFlush(Meas + "\n");
    Console.WriteLine(Meas);
    string response;
    io.Scanf("%s", out response);
    return response;
}

如果您希望 MeasureVoltage/MeasureCurrent 显得更短,请内联创建 Meas:

public string MeasureVoltage() => PerformMeasurement( $"MEAS:VOLT:{vt}?" );

编辑:如果您可以选择 enum 值名称来匹配所需的字符串,则可以完全删除 if

只需将第一行替换为:

public string MeasureVoltage()
{
     string Meas = "MEAS:VOLT:" + (vt == VoltageType.DC ? "DC?" : "AC?");
     return Measure(meas);
}

public string MeasureCurrent()
{
    string Meas = "MEAS:CURR:" + (ct == CurrentType.DC ? "DC?" : "AC?");
    return Measure(meas);
}

现在将两种方法之间的共同点提取到此:

private string Measure(string measure)
{
    io.PrintfAndFlush(Meas + "\n");
    Console.WriteLine(Meas);
    string response;
    io.Scanf("%s", out response);
    return response;
}

一个更好的方法是拥有两个独立的值,一个存储度量的类型(voltcurrent),另一个存储度量的类型(DCAC):

class MyType
{
    private string Type; // either CURR or VOLT
    private string otherType;  // either DC or AC

    public MyType(string type, otherType)
    { /* fill the members */ }
}

现在你甚至不需要两种方法,只需要这个:

public string Measure()
{
    var measure = "MEAS:" + this.Type + ":" + this.OtherType + "?\n";
    io.PrintfAndFlush(measure );
    Console.WriteLine(measure );
    string response;
    io.Scanf("%s", out response);
    return response;
}

现在简单地调用这个:

var m = new MyType("VOLT", "AC");
var result = m.Measure();

将打印 "MEAS:VOLT:AC?".

我认为这是我使用您提供的代码所能做的最好的事情:

public enum VoltageType { AC, DC}
public enum CurrentType { AC, DC}

public string MeasureVoltage()
{
    return Measure(MeasureType.Voltage);
}
public string MeasureCurrent()
{
    return Measure(MeasureType.Current);
}

private enum MeasureType {Voltage, Current}

private string Measure(MeasureType mt)
{
    var what = (mt == Voltage) ? "VOLT" : "CURR";
    var type = ((mt == MeasureType.Voltage && vt == VoltageType.AC) || 
                (mt == MeasureType.Current && ct == CurrentType.AC)) ? "AC" : "DC";

    // c# 6 or higher:
    var Meas = $"MEAS:{what}:{type}?";
    // for older versions of c#, use string.Format:
    // var Meas = string.Format("MEAS:{0}:{1}?", what, type);
    io.PrintfAndFlush(Meas + "\n");
    Console.WriteLine(Meas);
    string response;
    io.Scanf("%s", out response);
    return response;
}
public string MeasureVoltage()
{
    return DoMeasurement($"MEAS:VOLT:{vt.ToString()}?");
}

public string MeasureCurrent()
{
    return DoMeasurement($"MEAS:CURR:{ct.ToString()}?");
}

private string DoMeasurement(string Meas)
{
    io.PrintfAndFlush(Meas + "\n");
    Console.WriteLine(Meas);
    string response;
    io.Scanf("%s", out response);
    return response;
}

public enum VoltageType { AC, DC }
public enum CurrentType { AC, DC }

很简单,是吧? :)

$"" 语法就是所谓的 interpolated string,它在 C# 6.0 中可用。如果您使用的是早期版本,可以将其替换为 string.Format(),如下所示:

DoMeasurement(stringFormat("MEAS:VOLT:{0}?", vt.ToString()));

在这些情况下,您应该问自己的第一个问题是 "is it really the same?"。

如果是,那么你是对的,它可能是重复的,可能应该避免。请注意,我说过 "probably" - 这不是硬性规定,有时重复可能是必要的,甚至是好的,例如如果它增加了清晰度。

如果不是,那么避免看似重复的代码实际上可能是一件坏事。它不仅会使您的代码更加混乱,而且可能会完全忽略要点 - 例如如果你有一个狗对象和一个 table 对象,并决定因为它们都有 4 条腿,所以它们是一样的东西,你可能会遇到试图把咖啡放在 Spot 上的人——我很确定他反对!注意对相同方法的一些调用,特别是如果它们是像 WriteLine 这样的实用方法,则不算作重复。

在你的情况下,我认为你的行为有两个方面 - 确定要进行的测量,然后进行测量。

查看您的代码,您的 "taking the measurement" 东西是相同的;一个好的第一步可能是将它拉出到一个 "Measure" 方法中,像这样

public string MeasureVoltage()
{
    string Meas = "MEAS:VOLT:";
    if (vt == VoltageType.DC)
    {
       Meas += "DC?";
    }
    else
    {
       Meas += "AC?";
    }
    return Measure(Meas);
}

public string MeasureCurrent()
{
    string Meas = "MEAS:CURR:";
    if (ct == CurrentType.DC)
    {
       Meas += "DC?";
    }
    else
    {
       Meas += "AC?";
    }
    return Measure(Meas);
}

public string Measure(string Meas)
{
    io.PrintfAndFlush(Meas + "\n");
    Console.WriteLine(Meas);
    string response;
    io.Scanf("%s", out response);
    return response;
}

请注意,我保留了您的代码格式,以说明它是一个简单的“将 Measure 中的所有内容复制到一个单独的方法中,并将其替换为对 Measure(Meas).

的调用

更进一步;您的 Voltage 和 Current 枚举是相同的 - 从代码的角度来看,这没有什么意义,而且无论如何,这不像您获得 AC 电压和 DC 电流。考虑到这一点,您可以删除重复项 - 让我们调用替换 "PowerType" ,因为它涵盖了两者。此外,您可以决定此电源类型和测量类型都是您的测量方法的参数,并执行类似这样的操作

public enum PowerType { AC, DC }

public string Measure(string measurementType, PowerType pt)
{
    string powerString = pt == PowerType.AC ? "AC" : "DC";
    string measurement = measurementType + powerString;

    io.PrintfAndFlush(measurement + "\n");
    Console.WriteLine(measurement);
    string response;
    io.Scanf("%s", out response);
    return response;
}