C# 6中自动属性初始化语法的区别

9
以下是C# 6中初始化属性的几种表达方式之间的区别:
1. 从构造函数初始化自动属性
public class Context1
{
    public Context1()
    {
        this.Items = new List<string>();
    }

    public List<string> Items { get; private set; }
}

2:从后备字段初始化属性

public class Context2
{
    private readonly List<string> items;

    public Context2()
    {
        this.items = new List<string>();
    }

    public List<string> Items
    {
        get
        {
            return this.items;
        }
    }
}

3: C# 6中的自动属性新语法

public class Context3
{
    public List<string> Items { get; } = new List<string>();
}

4: C# 6中的自动属性新语法

public class Context4
{
    public List<string> Items => new List<string>();
}
2个回答

14

代码清单 3 是 C# 6 中与代码清单 2 对应的版本,其中支持字段已经在幕后提供。

代码清单 4:

public List<string> Items => new List<string>();

等同于:

public List<string> Items { get { return new List<string>(); } }

正如您所想象的那样,每次访问该属性时都会返回一个新的空列表。

列表2/3和4之间的区别在此问答中进行了进一步探讨,并提供了示例。

列表1只是具有getter和私有setter的自动属性。它不是只读属性,因为您可以在可以访问类型的任何私有成员的任何位置对其进行设置。只读属性(即仅具有getter的属性)只能在构造函数或属性声明中初始化,就像只读字段一样。


那么数字4就像一个常量,但具有引用类型的特性吗? - Ahmed Magdy
7
如果“constant”指的是“不断返回此值的新实例”(类似于https://xkcd.com/221),那么...嗯,我想是这样的。但这并不是“constant”的意思。引用类型无法成为常量也有其原因。 - BoltClock
数字1和2是否相似? - Ahmed Magdy

4

自动属性自动实现的属性的简称,开发人员不需要显式声明后备字段,并且编译器会在幕后设置一个。

1. 具有私有 setter 的自动属性

public class Context1
{
    public Context1()
    {
        this.Items = new List<string>();
    }

    public List<string> Items { get; private set; }
}

自动属性可以通过为访问器指定比属性更严格的可访问性,使setter和getter具有不同的可访问性。

其他示例包括:

public string Prop1 { get; private set; }
public string Prop2 { get; protected set; }
public string Prop3 { get; internal set; }
public string Prop4 { protected internal get; set; }

这些具有不同访问级别的存取器可以在访问级别确定的任何地方进行访问,而不仅仅是从构造函数中。

2. 具有支持字段的只读属性

public class Context2 { private readonly List items;

public Context2()
{
    this.items = new List<string>();
}

public List<string> Items
{
    get { return this.items; }
}

C#6之前,设置只读属性的唯一方法是显式地声明支持字段并直接设置它的值。

因为该字段具有readonly访问器,在对象构造期间才能设置。

3. 只读自动属性

public class Context3
{
    public List<string> Items { get; } = new List<string>();
}

从C#6开始,§2可以通过编译器处理,通过生成一个备份字段来处理读写自动属性,但在这种情况下,备份字段是只读的,并且只能在对象构造期间设置。

4. 表达式主体的只读自动属性

public class Context4
{
    public List<string> Items => new List<string>();
}

当属性的值每次获取时都会发生变化时,C#6 允许使用类似于 lambda 的语法声明 getter 的主体。

上述代码等同于以下代码:

public class Context4
{
    public List<string> Items
    {
        get { return new List<string>(); }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接