最佳答案
我有这个 API 函数:
public ResultEnum DoSomeAction(string a, string b, DateTime c, OtherEnum d,
string e, string f, out Guid code)
我不喜欢这样。因为参数顺序变得不必要的重要。添加新字段变得更加困难。很难看到传递的信息。将方法重构成更小的部分比较困难,因为它会产生另一个传递子函数中所有参数的开销。代码更难读。
我提出了一个最明显的想法: 让一个对象封装数据并传递它,而不是一个接一个地传递每个参数。以下是我的想法:
public class DoSomeActionParameters
{
public string A;
public string B;
public DateTime C;
public OtherEnum D;
public string E;
public string F;
}
这使我的 API 声明减少到:
public ResultEnum DoSomeAction(DoSomeActionParameters parameters, out Guid code)
不错嘛。看起来很单纯,但我们实际上引入了一个巨大的变化: 我们引入了可变性。因为我们之前所做的实际上是在堆栈上传递一个匿名的不可变物件: 函数参数。现在我们创建了一个非常易变的新类。我们创造了操纵 打电话的人状态的能力。真糟糕。现在我希望我的对象是不可变的,我该怎么做?
public class DoSomeActionParameters
{
public string A { get; private set; }
public string B { get; private set; }
public DateTime C { get; private set; }
public OtherEnum D { get; private set; }
public string E { get; private set; }
public string F { get; private set; }
public DoSomeActionParameters(string a, string b, DateTime c, OtherEnum d,
string e, string f)
{
this.A = a;
this.B = b;
// ... tears erased the text here
}
}
如您所见,我实际上重新创建了我最初的问题: 参数太多。很明显,这不是解决问题的办法。我该怎么办?实现这种不可变性的最后一个选项是使用“ readonly”结构,如下所示:
public struct DoSomeActionParameters
{
public readonly string A;
public readonly string B;
public readonly DateTime C;
public readonly OtherEnum D;
public readonly string E;
public readonly string F;
}
这使得我们可以避免带有太多参数的构造函数,并实现不可变性。实际上它解决了所有的问题(参数排序等)。然而:
这时我感到困惑,决定写下这个问题: 在 C # 中避免“参数过多”问题而不引入可变性的最直接的方法是什么?有没有可能在使用只读结构的同时,还没有糟糕的 API 设计?
澄清:
更新
这里提供的答案有不同的优缺点。因此,我想把它转换成一个社区维基。我认为每一个带有代码示例和优缺点的答案都可以为将来类似的问题提供很好的指导。我现在正在试图找出如何做到这一点。