如何确保在首次使用之前已初始化所有类字段
本文关键字:初始化 字段 何确保 确保 | 更新日期: 2023-09-27 18:35:10
假设我有一个做一些计算的类。这组计算需要一组参数作为输入。
public class Calculator
{
private CalculatorConfig _config;
public Calculator(CalculatorConfig config)
{
_config = config;
}
public Result Calculate(object obj){}
}
我的计算器配置类非常简单:
public class CalculatorConfig
{
public double param1;
public double param2;
...
}
我非常简单地初始化它
var config = new CalculatorConfig();
config.param1 = val;
....
var calculator = new Calculator(config);
我遇到的困境是,此类的用户可能会忘记初始化一些可能导致奇怪行为的字段。可能有意义的解决方案是将字段转换为属性,并且对于每个私有字段都有一个额外的布尔值,该布尔值将保存字段是否已初始化的信息。我还可以创建一个巨型构造函数,它将所有字段作为参数。
在这种情况下,您会选择什么方法?
谢谢
我将使用另一种方法。
- 将另一个名为 Check 的方法(可能是内部方法)添加到 CalculatorConfig 类中。
- 在执行 Compute 方法的过程中调用此方法。
-
在 Check 方法中验证每个参数并抛出自定义异常是出了问题
public class CalculatorConfig { public double param1; public double param2; ... internal void Check() { if(param1 == 0.0) throw new ArgumentException("Configuration error: param1 is not valid!"); if(param2 == 0.0) throw new ArgumentException("Configuration error: param2 is not valid!"); .... // other internal checks } } public class Calculator { private CalculatorConfig _config; public Calculator(CalculatorConfig config) { _config = config; } public Result Calculate(object obj) { // Throw ArgumentException if the configuration is not valid // Will be responsability of our caller to catch the exception _config.Check(); // Do your calcs ..... } }
如果所有参数都是绝对必需的,那么我会使用"巨型构造函数"选项。 这是一种更干净的方法来确保所有内容都已初始化,并且您不必添加额外的布尔属性并处理未初始化的情况。如果其中一个布尔值包含假值,你会怎么做?如何强制类的用户返回并添加这些值,除非使用某种异常处理?构造函数将简单地确保这些事情甚至不会在编译时发生,而不是在运行时发生。
我认为您的配置参数应该readonly
(可以说是private
,但可以通过属性访问)。然后,将警告设置为标记为错误。然后,当您无法初始化这些变量之一时,您将收到编译时错误
字段
CalculatorConfig.param1
永远不会分配到,并且将始终具有其默认值。
现在,您已经在编译时发现了问题。
在声明中设置默认值:
public class CalculatorConfig
{
public double param1 = 1.0; // a default value chosen by you
public double param2 = 2.0; // a default value chosen by you
}
或者更OO的解决方案:使用属性而不是公共字段,然后在创建实例时设置默认值:
public class CalculatorConfig
{
public double param1 {get;set;}
public double param2 {get;set;}
public CalculatorConfig()
{
InitParams();
}
private void InitParams()
{
param1 = 1.0;
param2 = 2.0;
}
}