带有ref的returnvalue与两个值

时间:2016-10-28 22:42:12

标签: c#

我今天与一位同事讨论了如何最好地回归两个价值观。 我们有三种不同的意见。问题的重点是,我们不能使用额外的类或结构(因此没有元组),这是这个问题中的首选答案:Clean Code - Are output parameters bad?

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

由于返回值+ ref值,选项2看起来很难看。

由于两个输出参数,选项1似乎也很难看,但事实上它看起来比第二个选项更清晰。

选项3看起来对我来说最干净。

哪些解决方案被认为是最干净的解决方案(如清洁代码中的bob martin一样干净),还是有其他选择来解决问题,我们可能没有想过?

2 个答案:

答案 0 :(得分:1)

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

在我看来,第二个选项是完全废话,因为out - 关键字应该完全符合您的要求,因此使用ref根本不需要。

第三种选择没问题,虽然非常混乱而且不那么容易。由于您无法使用元组并希望保持清晰的代码,因此请避免使用。

TL; DR:使用第一个选项。

答案 1 :(得分:1)

我只是想把它扔出去,虽然我永远不会在生产中这样做(至少对于公共API)。

另一种选择是使用dynamic返回类型。没有外面的参数。没有参考参考。只对要返回的值进行模糊处理:

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
}