返回与两个输出值比较的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在我看来是最干净的。
这些解决方案中哪一个被认为是最干净的解决方案(鲍勃·马丁认为干净的代码是干净的),或者是否有另一个解决问题的选择,我们可能没有想到?
一般来说,最干净的解决方案是不需要任何out
或ref
参数(最好是结构/类,元组也可以)。由于不允许使用类/结构或元组,这将是首选的方式,我仍然使用第一个选项,因为这是最简单的。
在我看来,第二个选项完全是胡扯,因为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
}