更新1
似乎要么我的英语太糟糕了,要么人们就是不给……要理解我要问的是什么,或者简单地看一下帖子的标题。
C#5规范明确指出:
因为备份字段不可访问,因此只能通过属性访问器读取和写入它,甚至在包含的类型中也是如此。这意味着自动实现只读或只写属性没有意义的,并且是不允许的。
public string MyProperty {get;}没有任何意义,但是编译器不需要发布getter,甚至不用为缺乏setter而争论不休。支持字段将使用默认值初始化。什么意思?这意味着设计人员花费了一些来实现验证,引入可能被忽略的功能。
现在让我们考虑一下C#6:
在C#6中,自动实现的属性的初始化是介绍。
public string FirstName { get; set; } = "Jane";或
public string FirstName { get; } = "Jane";在后一种情况下,还可以在构造函数中设置属性:
public class Program
{
public string ImagePath { get; }
public static void Main()
{
}
public Program()
{
ImagePath = "";
}
}但仅在声明属性的类的构造函数中。派生类不能设置属性值。
现在,如果这个属性没有在构造函数中初始化,那么问自己这个属性意味着什么:
property string My {get;}这是一项100%相当于C#5禁止的财产。它没有意义。
但是这种声明在C#5中是无效的,在C#6中是有效的,但是语义并没有改变:如果没有显式初始化,这个属性是无用的。
所以我才问:
为什么不显式初始化只读自动实现属性在c# 6中有效?
我希望看到的答案是:
我发现It's by design的答案完全无关紧要。这只是一个事实。我找理由。我不相信编译器设计者仅仅是抛硬币就决定编译器行为的改变。
这是一个好答案的示例。
原始问题
在VS2015中,编译该代码时没有出现错误:
public class Program
{
public string ImagePath { get; }
public static void Main()
{
Console.WriteLine("Hello World");
}
}然而,在VS2013中,我得到了错误:
编译错误(第5行,第28行):'Program.ImagePath.get‘必须声明一个主体,因为它没有标记为抽象或外部。自动实现的属性必须同时定义get和set访问器。
我知道可初始化的自动实现属性,如果VS2015字段获得默认值,即此处的null。但是有趣的是,为什么这个片段在C# 5中是无效的?
初始化自动实现的readonly属性没有显式初始化,在我看来有点奇怪。这很可能是一个错误,而不是意图。在这种情况下,我个人更希望编译器需要显式初始化:
public string ImagePath { get; } = default(string);
好的,我知道在构造函数中也可以分配这样的属性:
public class Program
{
public string ImagePath { get; }
public static void Main()
{
}
public Program()
{
ImagePath = "";
DoIt();
}
public void DoIt()
{
//ImagePath = "do it";
}
}
public class My : Program
{
public My()
{
//ImagePath = "asdasd";
}
}但是,如果编译器可以检查局部变量没有初始化,则属性也可以这样做。
那为什么它是这样的呢?
发布于 2016-05-12 18:52:17
编译器告诉您,自动属性必须同时定义两个访问器。例如,您可以用
public string ImagePath { get; private set; }假设您不打算在类之外设置该属性。
至于为什么您必须声明一个setter或者手动实现这个属性--那么,您可以读取的属性有什么用呢,但是它的类型总是返回默认值,因为没有方法来设置它?反过来说,您可以写入但既不能读取也不能链接到其设置器的属性有什么好处?
C# 6.0为您提供了拥有一次写一次、读取许多自动属性的选项;这是一个巨大的差异,因为值可以任意选择,允许您为具有不可变值的属性提供方便的语法。
发布于 2016-05-13 09:37:28
我不知道为什么你的问题被否决了。这是一个有趣的观察,但请记住,这不是一个突破性的变化-它只是‘新的功能’,是其他功能的‘剩余物’-初始化自动实现的属性。
这意味着它以前没有任何意义,但现在它已经意识到了。
此外,我认为这是有道理的。例如,当您有一些基类或接口时
interface IPerson
{
int Age { get; }
}总有一天,您可能希望在与年龄无关的情况下实现空对象模式。在c#5中,您必须编写public int Age { get { return 0; } },而在c#6中,您只需执行public int Age { get; },甚至可以将接口转换为抽象类,只需将其定义从interface更改为abstract class。
https://stackoverflow.com/questions/37195141
复制相似问题