如果为null,则设置为新实例的C#扩展方法
我有以下扩展方法来帮助我检查和实例化它们为null的对象。 前两个工作正常,但它们不是很有用。
public static bool IsNull(this T t) { return ReferenceEquals(t, null); } public static T NewIfNull(this T t, Func createNew) { if (t.IsNull()) { return createNew(); } return t; } public static void Ensure(this T t, Func createNew) { t = t.NewIfNull(createNew); }
最终我想做点什么
IList foo; ... foo.Ensure<IList>(() => new List());
但是,Ensure方法没有达到预期的效果,即如果它为null,则将foo
设置为List
的实例,否则基本上将其设置为自身。
如果你现在知道我可以调整Ensure方法来实现这一点我会很感激帮助。
谢谢,汤姆
您需要区分对象和变量 。 对象永远不能为null – 变量的值可以是。 你不是试图改变一个关于某个对象的东西(这会起作用) – 你试图改变调用者变量的值。
但是,默认情况下,参数按值传递,这意味着您的扩展方法会更改参数 (在方法中声明的变量),但这对调用者的变量没有影响。 通常,您可以将参数更改为ref
以实现pass-by-reference语义,但扩展方法不能具有ref
或out
first参数。
正如其他人所说的那样,使用null-coalescing运算符(??)是一个更好的选择。 请注意,在此表达式中:
foo = foo ?? new List();
除非foo
为null,否则不会构造新列表。 右手操作数??
除非需要,否则不予评估。
所以你试图复制空合并运算符?
foo = foo ?? new List();
您的Ensure
方法不起作用,因为您只是设置本地引用变量( t
)但不返回它 。 如果Ensure
返回t
,你可以这样做:
var list2 = list1.Ensure>();
但是,你不需要那个因为你可以使用?? 运营商:
var list2 = list1 ?? new List();
您的Ensure
方法不会执行任何操作,因为当t
不是ref
(或out
)参数时,为参数t
分配新内容不会更改调用方的任何内容。 相反,说
IList foo; ... foo = foo.NewIfNull(() => new List ());
可能会奏效,但正如其他人所说的那样,这并不是最美好的方式。