我有一个在这样的开关上执行初始化的构造函数:
class Foo {
public readonly int Bar;
public readonly object Baz;
public Foo(int bar, string baz) {
this.Bar = bar;
switch (bar) {
case 1:
// Boatload of initialization code
this.Bar = /* value based upon initialization code */
this.Baz = /* different value based upon initialization code */
case 2:
// Different boatload of initialization code
this.Bar = /* value based upon initialization code */
this.Baz = /* different value based upon initialization code */
case 3:
// Yet another...
this.Bar = /* value based upon initialization code */
this.Baz = /* different value based upon initialization code */
default:
// handle unexpected value
}
}
}
我仍在实现这一点,但一旦完成,它很容易变成几百行。我不喜欢有这么大的构造函数,但我不知道如何安全地绕过这个语言特性(而且绕过是我不想做的事情)。也许应该是暗示我正在尝试做的事情存在根本性的错误,但我不确定。
基本上,我想在我自己的自定义不可变类型中执行复杂的初始化。最好的方法是什么?在这种情况下,庞大的行数构造函数是一件可怕的事情吗?
更新:为了澄清起见,我想要做的是在一个类中保持不变性,该类将以可能的最佳方式以复杂的方式初始化实例。我正在编写一个代表随机生成的标记的类,FormatToken
通常是一个字符。
复杂的初始化是解析格式字符串(注意,我不是试图解析正则表达式来生成随机字符串,我不想在接下来的 20 辈子中这样做:))。我最初是在写一些可以通过构造函数参数接受输入的东西,例如
+ /// Format tokens
+ /// c{l} Lowercase Roman character in the ASCII range.
+ /// v{L} Uppercase Roman character in the ASCII range.
+ /// c Roman character in the ASCII range.
+ /// d Decimal.
+ /// d{0-9} Decimal with optional range, both minimum and maximum inclusive.
var rand = new RandomString("c{l}C{L}ddd{0-4}d{5-9}");
rand.Value == /* could equal "fz8318" or "dP8945", but not "f92781".
最终产生这个问题的类是代表这些标记中的每一个的类。初始化问题来自能够支持各种格式(ASCII 字符、罗马字母、小数、符号等)
这是有问题的实际代码:
internal class FormatToken {
public TokenType Specifier { get; private set; }
public object Parameter { get; private set; }
public FormatToken(TokenType _specifier, string _parameter) {
// discussion of this constructor at
// http://stackoverflow.com/questions/19288131/acceptable-way-to-set-readonly-field-outside-of-a-constructor/
Specifier = _specifier;
_init(_specifier, _parameter);
}
private void _init(TokenType _specifier, string _parameter) {
switch (_specifier) {
case TokenType.Decimal:
_initDecimalToken(_parameter);
break;
case TokenType.Literal:
Parameter = _parameter;
break;
case TokenType.Roman:
case TokenType.LowerRoman:
case TokenType.UpperRoman:
_initRomanToken(_specifier, _parameter);
break;
default:
throw new ArgumentOutOfRangeException("Unexpected value of TokenType.");
}
}
我readonly
最初使用它是因为我误解了使用它的原因。只需删除readonly
并替换为自动属性(即{ get; private set; }
会解决我的不变性问题。
这个问题更多是关于初始化任务的问题,而不是关于FormatToken
. 也许“如何执行复杂的、可能未知的初始化”现在是一个更好的问题标题。现在对我来说很明显,拥有一个巨大的开关是一个坏主意。工厂模式对于我正在做的事情当然很有趣,我认为回答了我的问题。我只想再给它几天。
非常感谢您到目前为止的想法!我将最初的示例代码留在此处,以使答案有意义。