Auto-属性 被表达式正文覆盖
Auto-property overridden with expression body
当使用抽象 getter-only 自动属性然后被表达式主体覆盖时 属性,Roslyn 编译器是否仍然创建使用支持字段?
据我了解,编译器将为自动 属性 创建一个支持字段,但不会为表达式主体 属性.
创建一个支持字段
基础摘要class
public abstract class FooPage
{
protected abstract string PageName { get; }
}
派生class
public class BarPage : FooPage
{
protected override string PageName => "FooBar";
}
我想知道在这种情况下会发生什么。我在 Roslyn 的维基中找到了这个..
https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#expression-bodies-on-property-like-function-members
但仍然不确定幕后究竟发生了什么。
首先,一般说明:如果您对此类问题非常感兴趣,解决它的最快方法是实际编译代码,然后使用 ildasm 或 ILSpy(在 IL 模式下)等工具查看生成的代码。显然,此结果不能概括为关于编译器应该做什么或必须做什么的明确陈述(只能由标准回答),但对于 "I wonder how" 问题,它通常就足够了。
表达式主体属性只是shorthand用于写出方法;它们永远不会导致生成支持字段。 BarPage
完全可以这样写:
public class BarPage : FooPage
{
protected override string PageName
{
get { return "FooBar"; }
}
}
这与 属性 在 FooPage
中的实现方式无关,也与它是否有支持字段无关。在您的示例中,它没有,因为这不是自动 属性:
protected abstract string PageName { get; }
这是一个抽象 属性,它在引入只读自动属性之前就已存在。它看起来很像 auto-属性,但它不是。以下不是合法的 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
,则会报错.您仍然不会直接访问支持字段(这很好;将客户端与有关如何实现 属性 的详细信息隔离开来是属性的全部要点)。
当使用抽象 getter-only 自动属性然后被表达式主体覆盖时 属性,Roslyn 编译器是否仍然创建使用支持字段?
据我了解,编译器将为自动 属性 创建一个支持字段,但不会为表达式主体 属性.
创建一个支持字段基础摘要class
public abstract class FooPage
{
protected abstract string PageName { get; }
}
派生class
public class BarPage : FooPage
{
protected override string PageName => "FooBar";
}
我想知道在这种情况下会发生什么。我在 Roslyn 的维基中找到了这个.. https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#expression-bodies-on-property-like-function-members
但仍然不确定幕后究竟发生了什么。
首先,一般说明:如果您对此类问题非常感兴趣,解决它的最快方法是实际编译代码,然后使用 ildasm 或 ILSpy(在 IL 模式下)等工具查看生成的代码。显然,此结果不能概括为关于编译器应该做什么或必须做什么的明确陈述(只能由标准回答),但对于 "I wonder how" 问题,它通常就足够了。
表达式主体属性只是shorthand用于写出方法;它们永远不会导致生成支持字段。 BarPage
完全可以这样写:
public class BarPage : FooPage
{
protected override string PageName
{
get { return "FooBar"; }
}
}
这与 属性 在 FooPage
中的实现方式无关,也与它是否有支持字段无关。在您的示例中,它没有,因为这不是自动 属性:
protected abstract string PageName { get; }
这是一个抽象 属性,它在引入只读自动属性之前就已存在。它看起来很像 auto-属性,但它不是。以下不是合法的 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
,则会报错.您仍然不会直接访问支持字段(这很好;将客户端与有关如何实现 属性 的详细信息隔离开来是属性的全部要点)。