C#6.0空传播运算符&财产分配 [英] C# 6.0 Null Propagation Operator & Property Assignment

查看:101
本文介绍了C#6.0空传播运算符&财产分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我注意到似乎很穷C#6.0中null传播运算符的局限性在于,您不能对已传播为null的对象调用属性 setters (尽管您可以对具有传播的对象调用属性 getters 传播为空)。正如您将从生成的IL (我已经反映到C#)中看到的那样,没有什么应该限制使用空传播调用属性设置器的能力。

I have noticed what appears to be quite a poor limitation of the null propagation operator in C# 6.0 in that you cannot call property setters against an object that has been null propagated (though you can call property getters against an object that has been null propagated). As you will see from the generated IL (which I have reflected into C#), there is nothing that should limit the ability to call property setters using null propagation.

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

To start with, I have created a simple class, with both Java style Get/Set methods, and a property with public getter/setter access.

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;
    }
}

我已经在以下测试了空传播的能力测试类。

I have tested the ability of null propagation in the following test class.

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;
    }
}




左手赋值的一面必须是变量,属性或
索引器。

The left-hand side of an assignment must be a variable, property or indexer.

但是您可能会注意到,Java方式通过调用 SetName(...)设置名称的方法,您可能还会注意到获取空传播属性的值也有效。

You may notice from this however that the Java way of setting the name, by calling SetName(...) works, and you may also notice getting the value of a null propagated property also works.

让我们看一下从此代码生成的C#:

Let's take a look at the C# that was generated from this code:

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一起使用,则使用三元运算符获取 Name null 的值。

Notice that when used against the SetName method, null propagation transforms to a straightforward if statement, and that when used against the Name property getter, a ternary operator is used to either get the value of Name or null.

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

One thing I have noticed here is the behavior difference between using an if statement and using the ternary operator: when using a setter, using an if statement would work, whereas using a ternary operator wouldn't.

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

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

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

在此示例中,我同时使用了 if 语句和三元运算符,然后在尝试将其分配给 Name 之前检查人员是否为 null 属性。 if 语句按预期工作;

In this example I am using both an if statement and the ternary operator to check whether person is null before attempting to assign to its Name property. the if statement works as expected; the statement using the ternary operator fails, as expected


对象引用未设置为对象的实例。

Object reference not set to an instance of an object.

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

In my opinion, the limitation comes from C# 6.0's ability to transform null propagation into either an if statement or a ternary expression. Had it been designed to use only if statements, property assignment would work via null propagation.

到目前为止,我尚未看到关于为什么不应该这样做的引人注目的论据,因此我仍在寻找答案!

So far, I have not seen one compelling argument as to why this SHOULD NOT be possible, therefore I am still looking for answers!

推荐答案

不是唯一的一个! SLaks 将此作为问题(现在此处

You're not the only one! SLaks raised this as an issue (now here)


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

Why can't I write code like this?

Process.GetProcessById(2)?. Exited + =委托人{};

,并在其短暂关闭为按设计

and after it was briefly closed as "By design"


?。运算符从不产生左值,所以这是设计使然。

the ?. Operator never produces an lvalue, so this is by design.

有人评论说这对属性设置程序和事件处理程序都是有益的。

someone commented that it would be good for property setters as well as event handlers


也许还会在请求中添加属性设置器,例如:

Maybe add also properties setters into request like:

Object?.Prop = false;

,它已作为C#7的功能请求重新打开。

and it was re-opened as a feature request for C#7.

这篇关于C#6.0空传播运算符&财产分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆