【问题标题】:Auto-property overridden with expression body用表达式主体覆盖的自动属性
【发布时间】:2017-07-12 12:23:24
【问题描述】:

当使用抽象的 getter-only 自动属性然后被表达式主体属性覆盖时,Roslyn 编译器是否仍然创建使用支持字段?

据我了解,编译器将为自动属性创建一个支持字段,但不会为表达式主体属性创建一个支持字段。

基础抽象类

public abstract class FooPage
{
     protected abstract string PageName { get; }
}

派生类

public class BarPage : FooPage
{
     protected override string PageName => "FooBar";
}

我想知道在这种情况下会发生什么。我在 Roslyn 的 wiki 中找到了这个。 https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#expression-bodies-on-property-like-function-members

但仍不确定幕后实际发生了什么。

【问题讨论】:

  • 如果你对这类事情很感兴趣,最快的解决方法是实际编译代码,然后使用ildasmILSpy之类的工具(在IL模式下)查看生成的代码。显然,这个结果不能概括为对编译器应该做什么或必须做什么做出明确的陈述(只能由标准来回答),但是对于“我想知道如何”的问题通常就足够了。
  • FooPage 没有声明自动属性——它声明了一个抽象属性。语法相同,但语义不同。如果您将属性设为virtual那么您将获得一个自动属性(带有支持字段)。当您知道这一点,并且表达式主体属性不使用支持字段,以及如何单独编译 FooPageBarPage 时,您应该能够自己推理出编译器必须(几乎必须)如何实现这个。
  • 感谢@JeroenMostert。
  • @JeroenMostert 为什么不将其发布为答案?
  • @svick:因为我是一个懒惰、懒散的可怜虫,经常需要一些明确的鼓励来发布答案,而不是即兴发挥……但现在已经解决了。

标签: c# roslyn c#-6.0


【解决方案1】:

首先,一般注意事项:如果你对这些事情很感兴趣,解决它的最快方法是实际编译代码,然后使用 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# 语法):

private readonly $PageNameBackingField;
protected string PageName 
{
    virtual get { return $PageNameBackingField; }
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-10
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    • 2020-12-03
    • 1970-01-01
    相关资源
    最近更新 更多