gpt4 book ai didi

c# - 区分 getter-only 属性和表达式主体属性?

转载 作者:行者123 更新时间:2023-12-02 01:13:51 28 4
gpt4 key购买 nike

是否可以使用反射来区分仅 getter 属性和表达式主体属性?

class MyClass
{
DateTime GetterOnly { get; }

DateTime ExpressionBody => DateTime.Now;
}

例如下面的方法如何完成?

enum PropertyKind
{
NotInteresting,

GetterOnly,

ExpressionBody,
}

PropertyKind GetPropertyKind(PropertyInfo propertyInfo)
{
if (propertyInfo.GetSetMethod(true) == null)
{
// what goes here??
}

return PropertyKind.NotInteresting;
}

相关帖子: What is the difference between getter-only auto properties and expression body properties?

最佳答案

首先我们必须定义我们的术语:

  • 自动属性 ​​- 具有由编译器自动生成的支持字段的属性。
  • 表达式主体属性 - 使用 => (lambda) 语法实现的属性。
  • 函数体属性 - 使用普通 {...} 语法实现的属性。

需要注意的是,不可能区分表达式主体属性和函数主体属性,因为实际上将为两者生成相同的 IL。

但是,我相信您真正想要的是能够区分自动属性和非自动属性。

这是可能的,因为编译器生成一个用 [CompilerGeneratedAttribute] 装饰的支持字段,并使用从属性派生的名称,可以对其进行测试。

支持字段名称当前始终为“ k__BackingField”(其中 PropertyName 是属性的名称),这对于 .Net 4.6 和 .Net Core 3.1 都是如此 - 但是当然,这并不能保证永远不会改变,因此任何依赖于此的代码都可能会在未来版本的 C# 编译器中崩溃。

尽管有相当大的警告,您可以编写一个方法来检查 PropertyInfo 是否实现了自动属性,如下所示:

public static bool IsAutoProperty(PropertyInfo property)
{
string backingFieldName = $"<{property.Name}>k__BackingField";
var backingField = property.DeclaringType.GetField(backingFieldName, BindingFlags.NonPublic | BindingFlags.Instance);

return backingField != null && backingField.GetCustomAttribute(typeof(CompilerGeneratedAttribute)) != null;
}

这会检查属性,以查看 (a) 它是否具有一个具有从属性名称派生的特定名称的支持字段,以及 (b) 该支持字段是编译器生成的。

我认为这不是一个好主意,因为它依赖于未记录的和凭经验确定的编译器行为,因此需要谨慎!

这是一个可编译的控制台应用程序来演示:

using System;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace ConsoleApplication1
{
static class Program
{
static void Main(string[] args)
{
var type = typeof(MyClass);

foreach (var property in type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
{
if (IsAutoProperty(property))
Console.WriteLine($"{property.Name} is an auto-property");
}
}

public static bool IsAutoProperty(PropertyInfo property)
{
string backingFieldName = $"<{property.Name}>k__BackingField";
var backingField = property.DeclaringType.GetField(backingFieldName, BindingFlags.NonPublic | BindingFlags.Instance);

return backingField != null && backingField.GetCustomAttribute(typeof(CompilerGeneratedAttribute)) != null;
}
}

class MyClass
{
DateTime GetterOnly { get; }

DateTime ExpressionBody => DateTime.Now;
}
}

输出:

GetterOnly is an auto-property

关于c# - 区分 getter-only 属性和表达式主体属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60637533/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com