C#6.0空传播操作员和属性分配

为彻底解释这个问题,这个问题已经彻底改变了。

我注意到C#6.0中的空传播操作符似乎是一个很差的限制,因为您无法针对已传播空的对象调用属性setter (尽管您可以针对已传播空的对象调用属性getter ) 。 正如你从生成的IL(我已经反映到C#中)所看到的那样,没有任何东西会限制使用空传播调用属性设置器的能力。

首先,我创建了一个简单的类,使用Java样式的Get / Set方法以及一个具有公共getter / setter访问权限的属性。

public class Person
{
    public Person(string name, DateTime birthday)
    {
        Name = name;
    }

    public string Name { get; set; }

    public void SetName(string name)
    {
        Name = name;
    }

    public string GetName()
    {
        return Name;
    }
}

我已经在下面的测试类中测试了无效传播的能力。

public class Program
{
    public static void Main(string[] args)
    {
        Person person = new Person("Joe Bloggs", DateTime.Parse("01/01/1991"));

        // This line doesn't work - see documented error below
        person?.Name = "John Smith";

        person?.SetName("John Smith");

        string name = person?.Name;
    }
}

作业的左侧必须是变量,属性或索引器。

然而,您可能会注意到,通过调用SetName(...)来设置名称的Java方式起作用,并且您可能还注意到获取空传播属性的值也适用。

让我们来看看从这个代码生成的C#:

public static void Main(string[] args)
{
    Person person = new Person("Joe Bloggs", DateTime.Parse("01/01/1991"));
    if (person != null)
    {
        person.SetName("John Smith");
    }
    string arg_33_0 = (person != null) ? person.Name : null;
}

注意,在对SetName方法使用时,空传播转换为简单的if语句,并且在对Name属性getter使用时,使用三元运算符来获取Namenull

我在这里注意到的一件事是使用if语句和使用三元运算符之间的行为差​​异:使用setter时,使用if语句可以工作,而使用三元运算符则不行。

public static void Main(string[] args)
{
    Person person = null;

    if (person != null)
    {
        person.Name = "John Smith";
    }

    person.Name = (person != null) ? "John Smith" : null;
}

在这个例子中,我使用if语句和三元运算符来检查person是否为null然后尝试分配给它的Name属性。 if语句按预期工作; 如预期的那样,使用三元运算符的语句失败

你调用的对象是空的。

在我看来,限制来自C#6.0将空传播转换为if语句或三元表达式的能力。 如果它被设计为只使用if语句,属性分配将通过空传播工作。

到目前为止,我还没有看到一个令人信服的论点,为什么不应该这样做,所以我仍然在寻找答案!


你并不是唯一的一个! SLaks提出这个问题

为什么我不能编写这样的代码?

Process.GetProcessById(2)?.Exited += delegate { };

并在短暂关闭后,按照“按设计”

这个? 运算符不会产生左值,所以这是设计。

有人评论说,这对财产制定者和事件处理者都是好事

也许还需要将属性设置器添加到请求中,如:

Object?.Prop = false;

并作为C#7的功能请求重新打开。


您不能以这种方式使用空传播运算符。

该运算符允许在评估表达式时传播空值。 它不能完全按照错误提示的方式用作分配的目标。

你需要坚持普通的旧的空检查:

if (a != null)
{
    a.Value = someValue;
}

试试像这样...

using System;

namespace TestCon
{
    class Program
    {
        public static void Main()
    {

        Person person = null;
        //Person person = new Person() { Name = "Jack" };

        //Using an "if" null check.
        if (person != null)
        {
            Console.WriteLine(person.Name);
            person.Name = "Jane";
            Console.WriteLine(person.Name);
        }

        //using a ternary null check.
        string arg = (person != null) ? person.Name = "John" : arg = null;
        //Remember the first statment after the "?" is what happens when true. False after the ":". (Just saying "john" is not enough)
        //Console.WriteLine(person.Name);

        if (arg == null)
        {
            Console.WriteLine("arg is null");
        }

        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
public class Person
{
    public string Name { get; set; }
}

}

链接地址: http://www.djcxy.com/p/13063.html

上一篇: C# 6.0 Null Propagation Operator & Property Assignment

下一篇: Shortcut &= acting like & not &&