C# 若变量为null,则赋值操作不执行任何操作?
如果某个变量已经是C# 若变量为null,则赋值操作不执行任何操作?,c#,c#-4.0,variable-assignment,C#,C# 4.0,Variable Assignment,如果某个变量已经是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 w
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
正如您所说,您需要的是
if
语句。当null
时,没有不赋值的条件运算符。在这种情况下,if
最合适(并非所有内容都必须是一行)
最佳选择:
if(a == null)
{
a = b;
}
或:
事实上,我认为后者作为一个简单的if
语句进行了优化
将分配给自身也不错。对于对象引用,它只是内存地址的分配。对于值类型,这只是一小块数据
如果a
实际上是一个属性设置器,请检查设置器内部的值是否有更改:
private string a;
public string A
{
get
{
return a;
}
set
{
if (value != a)
{
a = value;
}
}
}
虽然语法冗长
(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!
无论如何,我只会使用一行程序,如果如果(a为null){a=b;}
如果您关心在一个语句中完成这一切,那么您就不走运了-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);
public void AssignIfNull(参考T目标,T值)
{
如果(target==null)target=value;
}
// ...
AssignIfNull(参考a、b);
注意:上述内容不适用于属性,因为它们不能作为ref
参数传递
编辑:虽然上面的方法与类似,但这样的替代方法返回第一个参数的原始值,因此它可能比实现上面的方法更容易出错
或者您可以小心地重写初始语句,以便在初始赋值中使用空合并(??
)运算符。作为单个语句
var result = ((a == null) ? (a = b) : null);
然后可以丢弃result
的值。将a
和b
作为对象属性,并在a
的设置上添加一个Console.WriteLine()
,将显示它仅在以前为空时被分配
唯一能阻止它完全干净的是创建了一个一次性变量result
;希望它仍然足够干净
附录-我刚刚意识到您也可以使用:
var result = a ?? (a = b);
作为上述内容的更简短版本。同样地,a=b
仅在a
为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
案例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;
只是添加一个新变量来添加一个。否则它对我没有任何作用,所以我保留我的自我赋值并接受它。我认为C#8.0附带的新功能使这变得非常简单。有一个新功能可以检查变量,如果它为空,则设置值,如果不是空,则设置值
if (variable is null)
{
variable = expression;
}
只是做
variable ??= expression;
在您的情况下是:
a ??= b;
所以我假设a=a??b代码>已退出?@JoelRondeau出现,因此-OP不希望将a
重新分配给自身。然后,您必须使用if
来避免分配。我看不到任何其他选择。无论如何,做a=a
应该一点都不成问题,除非setter有很大的逻辑??如果a不为空,b将执行a=a,但您没有解释这是一个问题的原因。您是否有不需要a=a的原因?这对应用程序有害吗?a=a
是否仍会触发对象的set
方法?我真的不想被触发。哦,对不起,我的错。:)为什么要投否决票?这正是OP askedI没有否决的,但这只是一种模糊的方式来进行if
。事实上,?
就是这样做的。区别在于?返回必须分配给某个变量的表达式。摆脱该变量的唯一方法是让它返回lambdas并像javascript自动执行函数一样执行。我没有否决,这是一个有趣的攻击,但我认为代码最终有点神秘。我肯定会做一个if,但为了完整性,我不得不发布答案