返回与两个输出值比较的ref值

本文关键字:输出 比较 ref 两个 返回 | 更新日期: 2023-09-27 18:15:30

今天我和一个同事讨论了如何最好地返回两个值。我们有三个不同的意见。重要的是,我们不能使用额外的类或结构(因此没有Tuple),这是这个问题的首选答案:干净的代码-输出参数不好吗?.

public enum Offset
{
    None = 0,
    Training = 10,
    Cancel = 20
}
static void Main(string[] args)
{
    //Option 1
    int outValue = 0;
    Offset outOffset;
    HandleOffset(35, out outValue, out outOffset);
    //Option 2
    int refValue = 0;
    outOffset = SubtractOffset(ref refValue);
    //Option 3
    outOffset = GetOffsetById(35);
    int id = GetIdWithoutOffset(35);
}
//Option 1
public static void HandleOffset(int inValue, out int outValue, out Offset outOffset)
{
    outValue = inValue;
    outOffset = Offset.None;
    if ((inValue-(int)Offset.Cancel)>15)
    {
        outValue -= (int)Offset.Cancel;
        outOffset |= Offset.Cancel;
    }
    if ((inValue - (int)Offset.Training) > 15)
    {
        outValue -= (int)Offset.Training;
        outOffset |= Offset.Training;
    }
}
//Option 2
public static Offset SubtractOffset(ref int id)
{
    Offset offset = Offset.None;
    if ((id - (int)Offset.Cancel) > 15)
    {
        id -= (int)Offset.Cancel;
        offset |= Offset.Cancel;
    }
    if ((id - (int)Offset.Training) > 15)
    {
        id -= (int)Offset.Training;
        offset |= Offset.Training;
    }
    return offset;
}
//Option 3
public static Offset GetOffsetById(int id)
{
    Offset offset = Offset.None;
    if ((id - (int)Offset.Cancel) > 15)
    {
        offset |= Offset.Cancel;
    }
    if ((id - (int)Offset.Training) > 15)
    {
        offset |= Offset.Training;
    }
    return offset;
}
//Option 3
public static int GetIdWithoutOffset(int id)
{
    if ((id - (int)Offset.Cancel) > 15)
    {
        id -= (int)Offset.Cancel;
    }
    if ((id - (int)Offset.Training) > 15)
    {
        id -= (int)Offset.Training;
    }
    return id;
}

选项2看起来很丑,因为返回值+ ref值。

选项1看起来也很难看,因为有两个输出参数,但实际上它看起来比第二个选项更干净。

选项3在我看来是最干净的。

这些解决方案中哪一个被认为是最干净的解决方案(鲍勃·马丁认为干净的代码是干净的),或者是否有另一个解决问题的选择,我们可能没有想到?

返回与两个输出值比较的ref值

一般来说,最干净的解决方案是不需要任何outref参数(最好是结构/类,元组也可以)。由于不允许使用类/结构或元组,这将是首选的方式,我仍然使用第一个选项,因为这是最简单的。

在我看来,第二个选项完全是胡扯,因为out -关键字应该做你想做的事情,所以根本没有必要使用ref

第三个选项是可以的,尽管非常混乱而且不那么容易。既然不能使用元组,又想保持代码清晰,那就避免使用。

TL;DR:使用第一个选项

我只是把它扔在那里,尽管我永远不会在生产中这样做(至少对于公共API)。

另一种选择是使用动态返回类型。没有输出参数。没有参考参数。只是对返回值的混淆:

public class Program
{
    public static void Main()
    {
        dynamic offset = HandleOffset();
        Console.WriteLine(offset);
    }
    public static dynamic HandleOffset()
    {
        return new
        {
            Value = 64, 
            Offset = Offset.Cancel
        };
    }
}
public enum Offset
{
    None = 0,
    Training = 10,
    Cancel = 20
}