Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 若变量为null,则赋值操作不执行任何操作?_C#_C# 4.0_Variable Assignment - Fatal编程技术网

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,但为了完整性,我不得不发布答案