gpt4 book ai didi

c# - 引用类型的非初始化与空值

转载 作者:太空狗 更新时间:2023-10-29 19:55:13 25 4
gpt4 key购买 nike

引用类型变量未初始化或具有空值之间有区别吗?我在某处读到 non-init 意味着 null 但在其他地方我读到别的东西。谢谢!

最佳答案

请注意,字段 被隐式初始化为null,因此这只会影响变量。在纯 c# 中,您无法查询未初始化字段的值(您需要“明确赋值”),因此这是一个非问题。

不过,您可以通过滥用 IL 来做到这一点 - 通过声明一个 out 参数,并使用 DynamicMethod 编写一个不这样做的方法分配它(在 IL 中有效,但在 C# 中无效)。然后你会发现你会看到 null

这又是由于 IL 标志 (.locals init) 在 calling (C#) 上表示“在进入此方法之前为我清除堆栈”代码。 C# 编译器总是设置这个标志。如果您再次滥用 IL 编写不设置此标志的方法,您可能会看到垃圾。它可以是任何东西。但至此,你应该得到你得到的异常(exception):)

这是第一个示例(不是第二个,后者更复杂):

delegate void AbuseMe(out object foo);
static void Main() {
DynamicMethod dyn = new DynamicMethod("Foo",
typeof(void), new[] { typeof(object).MakeByRefType() });
dyn.GetILGenerator().Emit(OpCodes.Ret);
AbuseMe method = (AbuseMe) dyn.CreateDelegate(typeof(AbuseMe));
object obj; // this **never** gets assigned, by **any** code
method(out obj);
Console.WriteLine(obj == null);
}

为澄清起见,DynamicMethod 代码只是编写与此代码等效的代码,在 C# 中是不合法的:

static void Foo(out object whatever) { } // note, whatever is not assigned

之所以可行,是因为就 CLR 而言 out 不存在 - 只有 ref。所以这不是无效的 IL - 它只是语言 (C#) 赋予 out 意义并要求为其分配一个值。

问题是 Main() 仍然有 .locals init 标志;所以在幕后 obj 清除为 null(好吧,整个堆栈空间被简单地删除)。如果我在没有该标志的情况下从 IL 编译(并且有一些其他代码使堆栈空间变脏),我可能会看到垃圾。您可以在 Liran Chen's 上查看有关 .locals init 的更多信息博客。

但要回答这个问题:

  • 对于字段:未初始化的引用类型字段是null - 由规范保证
  • 对于变量:你不能问,但是作为实现细节(不应该依赖):是的,它将是null 即使你不能问;p

关于c# - 引用类型的非初始化与空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4770426/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com