Daniel在他的回答中指出(除非我读错了)ECMA-335 CLI规范允许编译器生成抛出NullReferenceException以下DoCallback方法的代码.
class MyClass {
private Action _Callback;
public Action Callback {
get { return _Callback; }
set { _Callback = value; }
}
public void DoCallback() {
Action local;
local = Callback;
if (local == null)
local = new Action(() => { });
local();
}
}
Run Code Online (Sandbox Code Playgroud)
他说,为了保证NullReferenceException不抛出,volatile关键字应该用于_Callback或lock应该在线周围使用local = Callback;.
有人可以证实这一点吗?而且,如果确实如此,Mono和.NET编译器之间在这个问题上的行为是否存在差异?
编辑
这是标准的链接. …
所以这就是问题的关键:Foo.Bar可以返回null吗?为了澄清,'_bar'在被评估为非null并且在返回值之前可以设置为null吗?
public class Foo
{
Object _bar;
public Object Bar
{
get { return _bar ?? new Object(); }
set { _bar = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
我知道使用以下get方法不安全,并且可以返回null值:
get { return _bar != null ? _bar : new Object(); }
Run Code Online (Sandbox Code Playgroud)
更新:
另一种看待同一问题的方法,这个例子可能更清楚:
public static T GetValue<T>(ref T value) where T : class, new()
{
return value ?? new T();
}
Run Code Online (Sandbox Code Playgroud)
并再次询问GetValue(...)是否会返回null?根据你的定义,这可能是也可能不是线程安全的...我猜正确的问题陈述是询问它是否是一个关于价值的原子操作...... David Yaw已经通过说上面的函数等效来定义问题了以下内容:
public static T GetValue<T>(ref T value) where T : class, new()
{
T result = value;
if …Run Code Online (Sandbox Code Playgroud) 每个人都知道这不是线程安全的:
public StringBuilder Builder
{
get
{
if (_builder != null)
_builder = new StringBuilder();
return _builder;
}
}
Run Code Online (Sandbox Code Playgroud)
那这个呢?
public StringBuilder Builder
{
get { return _builder ?? (_builder = new StringBuilder()); }
}
Run Code Online (Sandbox Code Playgroud)