如果该变量已经是null
,我想有条件地为变量赋值。此外,如果该变量尚未null
,我希望没有发生,我希望能够使用单个运算符完成所有操作。
object a = null;
object b = new Something();
// this is essentially what I want but done with an operator:
if(a == null)
{
a = b;
}
// this is all I feel I have to work with,
a = a || b;
a = a ?? b;
a = a == null ? b : a;
// the above methods all end up performing a = a if a is not null
答案 0 :(得分:7)
如果你担心在一个声明中完成这一切,那你就不走运了 - C#在语言层面没有这个功能,并且不支持操作员声明(如同F#)或重载赋值运算符(与C ++一样)。但是,有一些选项,如果没有你想要的那么优雅。
if
语句,正如您所提到的,尽管它可以写成一行
if(a == null) a = b;
使用ref
参数
public void AssignIfNull<T>(ref T target, T value)
{
if(target == null) target = value;
}
// ...
AssignIfNull(ref a, b);
注意上面的不使用属性,因为它们不能作为ref
参数传递。
编辑:虽然上面的内容类似于Interlocked.CompareExchange
,但这样的替代方法会返回第一个参数的原始值,因此它可能更多地证明了比实施上述方法还要好。
或者你可以仔细地重写你的初始语句,以便在初始赋值中使用null-coalescing(??
)运算符。
答案 1 :(得分:3)
正如您所说,if
声明是您所需要的。在null
时没有指定的条件运算符。在这种情况下if
最合适(并非一切都必须是oneliner)。
最佳选择:
if(a == null)
{
a = b;
}
或者:
a = a ?? b;
事实上,我认为后者被优化为简单的if
语句。
将a
分配给自己也不错。使用对象引用,它只是内存地址的赋值。对于值类型,这只是一小部分数据。
如果a
实际上是属性设置器,请在setter内部检查值是否有变化:
private string a;
public string A
{
get
{
return a;
}
set
{
if (value != a)
{
a = value;
}
}
}
答案 2 :(得分:3)
虽然语法是详细的
(a is null?()=>a=b:(Action)(()=>{}))();
让我们分开
( // Expression starts here
a is null // If a == null...
? () => a = b // return lambda that assigns a = b
: (Action) ( // Else return next lambda casted as Action
() => {} // Empty lambda that does nothing
) // End cast
) // Expression ends here
(); // Execute it!
无论如何,如果if(a is null) { a = b; }
答案 3 :(得分:2)
我自己遇到这种情况,我决定检查我的代码处理这个问题。我倾向于有两个解决方案,都涉及空合并运算符。
案例1:初始化。使用上面的值,这将成为:
object a = null ?? something;
显然,我不会写那行代码(如果没有别的话,resharper就会抱怨)。但这是正在发生的事情的本质。如果我在创建a
时有两个(或更多)值,那么我就这样写了。
案例2:从不设置a
,但在使用??
时使用a
。在这种情况下,代码将是:
MethodTakingA(a ?? b);
如果有多个方法调用或其他我需要使用??
的地方,那么这是一个坏主意。
还有第三种情况,我会做你正在避免的确切任务。也就是说,当我的方法的一个参数可能为null时,我在这种情况下有一个默认值(而不是抛出ArgumentNullException
)。这是一个例子:
public void Foo(string str)
{
str = str ?? String.Empty;
//Use str as needed below without fear that it might be null.
}
对于这种情况,我想要一个更好的答案,但我当然不会编写代码,微观优化该分配是值得的,以及理论答案
string localStr = str ?? String.Empty;
只是添加一个新变量来添加一个。否则我没有任何目的,所以我保留自己的任务并与之共存。
答案 4 :(得分:1)
作为单一陈述,
var result = ((a == null) ? (a = b) : null);
然后可以丢弃result
的值。将a
和b
作为对象属性,并在Console.WriteLine()
的设置上添加a
将显示它仅在以前为空时指定。
唯一阻止它完全清洁的是创建了一次性变量result
;希望它还够干净。
附录 - 我刚刚意识到你也可以使用:
var result = a ?? (a = b);
作为上述更短的版本。同样,a = b
仅在a
为null
时进行评估。
答案 5 :(得分:0)
我认为C#8.0附带的新功能使此操作变得非常容易。有一个新的??= operators会检查变量,如果变量为null,则设置值,否则为空。
if (variable is null)
{
variable = expression;
}
只是像
variable ??= expression;
您的情况是:
a ??= b;