C#6.0空传播运算符&财产分配 [英] C# 6.0 Null Propagation Operator & Property Assignment
问题描述
为了彻底解释,已经彻底修改了这个问题。
我注意到似乎很穷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!
推荐答案
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屋!