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使用时,使用三元运算符来获取Name
或null
。
我在这里注意到的一件事是使用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