C# 自动属性被表达式体覆盖

C# 自动属性被表达式体覆盖,c#,roslyn,c#-6.0,C#,Roslyn,C# 6.0,当使用抽象getter-only自动属性,然后用表达式体属性重写这些属性时,Roslyn编译器是否仍然创建一个use-the-backing字段 据我所知,编译器将为auto属性创建一个支持字段,但不会为expression body属性创建一个支持字段 基本抽象类 public abstract class FooPage { protected abstract string PageName { get; } } public class BarPage : FooPage {

当使用抽象getter-only自动属性,然后用表达式体属性重写这些属性时,Roslyn编译器是否仍然创建一个use-the-backing字段

据我所知,编译器将为auto属性创建一个支持字段,但不会为expression body属性创建一个支持字段

基本抽象类

public abstract class FooPage
{
     protected abstract string PageName { get; }
}
public class BarPage : FooPage
{
     protected override string PageName => "FooBar";
}
派生类

public abstract class FooPage
{
     protected abstract string PageName { get; }
}
public class BarPage : FooPage
{
     protected override string PageName => "FooBar";
}
我想知道在这种情况下会发生什么。我在Roslyn的维基上找到了这个。。


但是仍然不确定封面下到底发生了什么。

首先,请注意:如果您对这些问题非常感兴趣,最快的解决方法是实际编译代码,然后使用ildasm或ILSpy(在IL模式下)等工具查看生成的代码。显然,这一结果不能被概括为对编译器应该做什么或必须做什么做出明确的陈述(这只能用标准来回答),但对于“我想知道”问题通常是足够的

表达式体属性只是写出方法的简写;它们永远不会导致生成支持字段
BarPage
可以这样完整地写出:

public class BarPage : FooPage
{
     protected override string PageName 
     {
         get { return "FooBar"; }
     }
}
这与属性在
FooPage
中的实现方式无关,也与该属性是否有支持字段无关。在您的示例中,它不是,因为这不是自动属性:

protected abstract string PageName { get; }
这是一个抽象属性,在引入只读自动属性之前就存在。它看起来很像一个汽车财产,但它不是一个。以下不是合法的C#语法,但更好地反映了IL翻译:

protected string PageName 
{
    abstract get;
}
这里没有后备字段。另一方面,以下是只读自动属性,并且有一个支持字段:

protected virtual string PageName { get; }
想象它是这样的(同样,不是合法的C#语法):


但是,至关重要的是,这仍然对
BarPage
中的实现没有任何影响,因为那里的getter不依赖于基本实现。如果显式引用了
base.PageName
,您会发现,如果基本属性是
virtual
,则此操作有效,如果基本属性是
abstract
,则会出现错误。您仍然不能直接访问backing字段(这很好;将客户机与如何实现属性的细节隔离是属性的全部要点)。

首先,一般性说明:如果您对这些问题非常感兴趣,解决它的最快方法是实际编译代码,然后使用ildasm或ILSpy(在IL模式下)等工具查看生成的代码。显然,这一结果不能概括为编译器应该做什么或必须做什么(这只能由标准来回答),但对于“我想知道如何”的问题,它通常就足够了

表达式体属性只是写出方法的简写;它们永远不会导致生成支持字段
BarPage
可以这样完整地写出:

public class BarPage : FooPage
{
     protected override string PageName 
     {
         get { return "FooBar"; }
     }
}
这与属性在
FooPage
中的实现方式无关,也与该属性是否有支持字段无关。在您的示例中,它不是,因为这不是自动属性:

protected abstract string PageName { get; }
这是一个抽象属性,在引入只读自动属性之前就存在。它看起来很像一个汽车财产,但它不是一个。以下不是合法的C#语法,但更好地反映了IL翻译:

protected string PageName 
{
    abstract get;
}
这里没有后盾。另一方面,以下是只读自动属性,并且有一个支持字段:

protected virtual string PageName { get; }
想象它是这样的(同样,不是合法的C#语法):


但是,至关重要的是,这仍然对
BarPage
中的实现没有任何影响,因为那里的getter不依赖于基本实现。如果显式引用了
base.PageName
,您会发现,如果基本属性是
virtual
,则此操作有效,如果基本属性是
abstract
,则会出现错误。您仍然不能直接访问backing字段(这很好;将客户机与如何实现属性的细节隔离是属性的关键所在)。

如果您对这些问题非常感兴趣,解决它的最快方法是实际编译代码,然后使用
ildasm
ILSpy
(在IL模式下)等工具查看生成的代码。显然,这一结果不能概括为编译器应该做什么或必须做什么(这只能通过标准来回答),但对于“我想知道怎么做”的问题,它通常就足够了。
FooPage
没有声明自动属性——它声明了一个抽象属性。语法相同,但语义不同。如果您将属性
改为虚拟属性
,那么您就拥有了一个自动属性(带有支持字段)。当您知道,表达式体属性不使用支持字段,以及
FooPage
BarPage
是如何单独编译的,您应该能够自己解释编译器必须如何编译(几乎是必须的)实现这一点。谢谢@Jeroemoster@Jeroemoster你为什么不把它作为一个答案发布?@svick:因为我是一个懒惰、懒惰的可怜虫,经常需要一些明确的鼓励来发布答案,而不是即兴的评论。。。但是现在已经解决了。如果您对这些问题非常感兴趣,最快的解决方法是实际编译代码,然后使用像
ildasm
ILSpy
(在IL模式下)这样的工具查看生成的代码。显然,这一结果不能概括为编译器应该做什么或必须做什么(这只能通过标准来回答),但对于“我想知道怎么做”的问题,它通常就足够了。
FooPage
没有声明自动属性——它声明了一个抽象属性。语法