我想检查变量是否在运行时以编程方式初始化。为了让这个原因不那么神秘,请参阅以下不完整的代码:
string s;
if (someCondition) s = someValue;
if (someOtherCondition) s = someOtherValue;
bool sIsUninitialized = /* assign value correctly */;
if (!sIsUninitialized) Console.WriteLine(s) else throw new Exception("Please initialize s.");
并完成相关部分。
一个 hacky 解决方案是使用默认值初始化 s:
string s = "zanzibar";
然后检查它是否改变:
bool sIsUninitialized = s == "zanzibar";
但是,如果
someValue
或 someOtherValue
恰好也是“zanzibar”怎么办?然后我有一个错误。还有更好的办法吗?
如果编译器知道变量尚未初始化,代码甚至不会编译。
string s;
if (condition) s = "test";
// compiler error here: use of unassigned local variable 's'
if (s == null) Console.Writeline("uninitialized");
在其他情况下,如果变量可能尚未初始化,您可以使用
default
关键字。 例如,在以下情况下:
class X
{
private string s;
public void Y()
{
Console.WriteLine(s == default(string)); // this evaluates to true
}
}
文档指出default(T)将为引用类型提供
null
,为值类型提供0
。 正如评论中所指出的,这实际上与检查 null 相同。
这一切都掩盖了这样一个事实:在第一次声明变量时,您应该真正将变量初始化为
null
或其他值。
在 C# 2.0 中,您可以使用 Nullable 运算符为迄今为止的值类型设置初始值 null,从而允许执行以下操作:
int? x = null;
if (x.HasValue)
{
Console.WriteLine("Value for x: " + num.Value);
}
其产量: “x 的值:空”。
默认分配即可
null
,而不是字符串值
这是一种方法:
string s;
if (someCondition) { s = someValue; }
else if (someOtherCondition) { s = someOtherValue; }
else { throw new Exception("Please initialize s."); }
Console.WriteLine(s)
这可能更适合检查字符串是否为 null,因为也许 someValue 是有时可以返回 null 的方法。 换句话说,也许 null 是初始化字符串的合法值。
我个人比
isInitialized
旗帜更喜欢这个。 除非必要,为什么要引入额外的标志变量呢? 我不认为它更具可读性。
您可以保留一个单独的标志来指示字符串已初始化:
string s = null;
bool init = false;
if (conditionOne) {
s = someValueOne;
init = true;
}
if (conditionTwo) {
s = someValueTwo;
init = true;
}
if (!init) {
...
}
这将处理分配
s
时的情况,包括分配 null
、空字符串或 "zanzibar"
时的情况。
另一个解决方案是制作一个静态字符串来表示“未初始化”值,并使用
Object.ReferenceEquals
而不是 ==
来检查它是否已更改。然而,bool
变量方法更明确地表达了你的意图。
我同意 Vytalyi 的观点,即应尽可能使用默认值 null,但是,并非所有类型(如 int)都可以为 null。您可以将变量分配为可空类型,如 David W 所解释的,但这可能会破坏大型代码库中的许多代码,因为必须在访问之前将可空类型细化为其原始类型。
这个通用方法扩展应该对那些处理大型代码库的人有所帮助,其中主要设计决策已经由前辈做出:
public static bool IsDefault<T>(this T value)
=> ((object) value == (object) default(T));
如果您从头开始,只需利用可空类型并将其初始化为 null; C# 功能的实现是有原因的。
我选择永远不会使用的初始化值,典型值包括
String.Empty
、null
、-1
和256个字符的随机字符串生成器。
我建议用
null
: 初始化变量
MyType? myVar = null;
然后您可以使用以下方法检查它是否已设置为非空值:
var isSet = myVar != null;
一般情况下,将默认值指定为
null
或 String.Empty
。 对于无法使用这些“空”值的情况,请定义一个常量来表示特定于应用程序的未初始化值:
const string UninitializedString = "zanzibar";
然后每当您想要初始化或测试初始化时引用该值:
string foo = UnininitializedString;
if (foo == UninitiaizedString) {
// Do something
}
请记住,字符串在 C# 中是不可变常量,因此实际上只有一个
UninitializedString
实例(这就是比较有效的原因)。