【问题标题】:c# shorthand for if not null then assign valuec# if not null then assign value 的简写
【发布时间】:2019-06-06 21:58:26
【问题描述】:

现在c#中是否有任何简写可以减少以下代码:

var testVar1 = checkObject();
if (testVar1 != null)
{
      testVar2 = testVar1;
}

在这种情况下,如果 checkObject() 结果中的 testVar1 不为空,则只想分配 testVar2(testVar2 有一个会触发代码的设置器)。试图思考如何使用空合并的东西,但没有真正解决。

添加到这个 testVar2 上有代码在它的 setter 上触发,所以如果值为 null,不希望 testVar2 被设置为任何值。

    public MyObj testVar2
    {
        get { return _testVar2; }
        set
        {
            _testVar2 = value;
            RunSomeCode();                
        }
    }

【问题讨论】:

  • testVar2 = testVar1 ?? testVar2;;意味着它将设置testVar2testVar1 如果它不为空,如果它为空,它将设置testVar2testVar2。示例:dotnetfiddle.net/hUPYDU
  • testVar2 = testVar1 != null ? testVar1 : testVar2;
  • 我明白了,如果 testVar1 为 null,但我不希望 testVar2 被设置为任何东西,即使它被设置为自身,它也会命中 setter 方法。
  • 现在我看到避免使用二传手是主要目标,还有一个额外的建议。我认为在那之后,我们就没有语法糖了

标签: c# shorthand null-coalescing-operator null-coalescing


【解决方案1】:

有一对!

三元运算符:

testvar2 = testVar1 != null ? testvar1 : testvar2;

应该是完全一样的逻辑。

或者,如评论所述,您可以使用空合并运算符:

testVar2 = testVar1 ?? testVar2

(虽然现在也被评论了)

或者第三种选择:编写一次方法,然后按你喜欢的方式使用它:

public static class CheckIt
{
    public static void SetWhenNotNull(string mightBeNull,ref string notNullable)
    {
        if (mightBeNull != null)
        {
            notNullable = mightBeNull;
        }
    }
}  

并称它为:

CheckIt.SetWhenNotNull(test1, ref test2);

【讨论】:

  • 您希望该函数究竟能做什么?
  • @DavidG 这并不完全正确,但现在已修复,如果 test1 有值,则将 test2 设置为 test1。 (如果 test1 的值为 null,则不使用 set 方法)
  • 我认为这个函数应该被称为SetUnlessNull(),因为赋值发生在第一个参数为not null的时候。
  • @foraidt 完全公平!
【解决方案2】:

不是该问题的答案,但我在 Google 上搜索了“c# shorthand set if null”并首先登陆这里,所以仅供其他人使用。问题是“if NOT null then assign value的简写”,下面是“if null then assign value的简写”。

在 C# 8.0+ 中你可以使用??=:

// Assign testVar1 to testVar2, if testVar2 is null
testVar2 ??= testVar1;

// Which is the same as:
testVar2 = testVar2 ?? testVar1;

// Which is the same as:
if(testVar2 == null)
{
   testVar2 = testVar1;
}

还有我最喜欢的:

// Create new instance if null:
testVar1 ??= new testClass1();

// Which is the same as:
if(testVar1 == null)
{
   testVar1 = new testClass1();
}

只是一个我经常使用的例子:

List<string> testList = null;

// Add new test value (create new list, if it's null, to avoid null reference)
public void AddTestValue(string testValue)
{
   testList ??= new List<string>();
   testList.Add(testValue);
}

【讨论】:

  • 第一个注释行是否正确“// 如果 testVar2 为 null,则分配给 testVar1” - 还是应该是“如果 testVar2 为 null,则分配给 testVar2”?如果 testVar2 为 null,则详细的第三个示例将 testVar1 分配给 testVar2。
  • @Swampie 应该是正确的,A ??= B 表示赋值给B,但前提是源(A)为空,否则保留该值。 “如果 testVar2 为 null,则分配给 testVar2”没有意义? testVar2 为 null 或者它有一个值,所以“如果 testVar2 为 null,则分配给 testVar2”不会改变任何东西。看我的最后一个例子,我想这更清楚,如果列表为空,则分配给一个新列表。想象一下它在一个循环或其他东西中,所以在添加第一个项目之前,您创建一个新列表,对于您使用现有列表的其他项目(因为 testList 不是 null 并且不会创建新列表)。
  • 你可以用最后一个例子更进一步: (testList ??= new List()).Add(testValue);括号返回分配给 testList 的值。
  • 哦对,没错,这应该是最短的路了;)
  • +1 用于使用示例创建一个对象,如果为 null,这在其他地方没有提到很多,也是我最喜欢的!
【解决方案3】:

您可以使用null-coalescing operator,如下所示:testVar2 = testVar1 ?? testVar2。如果testVar1 为空,您可以将?? testVar2 替换为您想要设置的任何值。

【讨论】:

  • +1 您的答案有点短且令人困惑,但文档链接让我找到了最适合我的答案 testVar2 ??= testVar1。
【解决方案4】:

你提到testVar2 有一个设置器,它在设置时触发一些事件。如果您没有检查 testVar2 是否被设置为自身,则事件仍将使用空合并运算符(或三元运算符)触发。

我认为您要么必须检查 testVar2 是否在其设置器中设置为自身,要么执行您现在正在做的事情。

    public MyObj testVar2
    {
        get { return _testVar2; }
        set
        {
            if (_testVar2 != value)
            {
               _testVar2 = value;
               RunSomeCode();
            }                
        }
    }

我认为这完全是我的意见,但我会保留它现在的样子。我认为它比速记更能传达意图。

testVar2 = testVar1 ?? tesrVar2 说,“将testVar2 设置为testVar1。除非testVar1 为空。然后将testVar2 设置为testVar2”。

if (testVar1 != null)
{
   testVar2 = testVar1;
}

说,“如果testVar1 不为空,则将testVar2 设置为testVar1”。

【讨论】:

    【解决方案5】:

    如果您不想让 testVar2 设置为 null,那么在设置器本身中检查 null 可能更有意义。否则,您必须记住在尝试设置时检查null

    请注意,我还修改了大小写以符合 C# 标准

    private MyObj testVar2;
    
    public MyObj TestVar2
    {
        get { return testVar2; }
        set
        {
            if (value == null) return;      // Or throw an ArgumentNullException
            if (testVar2 == value) return;  // No need to RunSomeCode if the value isn't changing
    
            testVar2 = value;
            RunSomeCode();                
        }
    }
    

    现在,如果您仍然关心在设置属性之前检查 null(例如,如果您决定在 null 值的情况下抛出异常),那么您的原始设置没有问题代码(三元/空合并解决方案似乎有点“浪费”,因为它们可能会为自己设置一些东西),您可以在一行中完成:

    if (testVar1 != null) SomeClass.TestVar2 = testVar1;
    

    但是,如果您只是创建 testVar1 以捕获对 CheckObject() 的调用结果,那么 null-coalescing 运算符更有意义,因为您不必创建变量存储值:

    SomeClass.TestVar2 = CheckObject() ?? SomeClass.TestVar2;
    

    【讨论】:

      猜你喜欢
      • 2019-10-22
      • 1970-01-01
      • 2015-07-06
      • 2011-05-13
      • 1970-01-01
      • 1970-01-01
      • 2011-12-24
      • 2019-03-23
      • 2021-07-09
      相关资源
      最近更新 更多