C# 属性总是有备份字段 "behind the scene" 吗?
Do C# properties always have backup fields "behind the scene"?
我知道当我们在 C# 中使用属性时,编译器总是在 CIL 中为它们生成 getters 和 setters(即 get_PropertyName 和 set_PropertyName ),例如,考虑以下代码:
class Program
{
class Test
{
public string Name { get; set; }
}
static void Main(string[] args)
{
//Here I'm using reflection to inspect methods of Test class
Type type = typeof(Test);
foreach (var item in type.GetMethods())
{
Console.WriteLine(item.Name);
}
}
}
这个程序会用Test
的方法产生输出,其中会有get_Name
和set_Name
- getter和setters我在说。
根据我的理解,如果 getters 和 setter 被创建 "behind the scenes" 那么也应该从 which/to 创建一个支持字段,其中 getters 和setter get/set 值。
因此,根据前面的示例,我可以使用反射来检查 Test class 的字段,例如:
static void Main(string[] args)
{
Type type = typeof(Test);
foreach (var item in type.GetFields())
{
Console.WriteLine(item.Name);
}
}
这个程序的输出是空的,我假设这是因为创建的支持字段具有 private
访问权限,所以我们看不到它。但是因为我不知道如何检查它,你能告诉我是否总是创建一个支持字段(即使我们有一个简单的 属性 只有 get;
和 set;
) ?
如果您指的是像这样的简单属性:
{get;set;}
或:
{get;}
那么是的,有一个字段;将 BindingFlags.NonPublic | BindingFlags.Instance
添加到您的 GetFields()
调用中,您会看到它:
foreach (var item in type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
{
Console.WriteLine(item.Name);
}
它通常有一个不可发音的名字,涉及 <>
- 你的名字在我的机器上是 <Name>k__BackingField
- 但是:这个名字是一个编译器特性(尽管很多序列化等库都使用它,所以不太可能改变)。
但是:不,属性本身 并不总是涉及字段;例如:
public int Value => 42; // no field
或
public int Name { get { return obj.Name; } set { obj.Name = value; } }
But since I don't know how to check it, can you please let me know if a backup field always get created (even if we have a simple property with only get; and set; ?
自动实现属性,例如
public int ReadWriteProperty { get; set; }
public int ReadOnlyProperty { get; }
确实总是会有一个由编译器生成的支持字段。但是,如果您提供自己的 getter/setter 实现,则编译器不会生成字段:
public int Zero => 0;
public int IgnoresSetter
{
get { return 10; }
set { /* Meh. Whatever you say, I'm still going to return 10 in the getter... */ }
}
这些都不会导致生成字段。
我知道当我们在 C# 中使用属性时,编译器总是在 CIL 中为它们生成 getters 和 setters(即 get_PropertyName 和 set_PropertyName ),例如,考虑以下代码:
class Program
{
class Test
{
public string Name { get; set; }
}
static void Main(string[] args)
{
//Here I'm using reflection to inspect methods of Test class
Type type = typeof(Test);
foreach (var item in type.GetMethods())
{
Console.WriteLine(item.Name);
}
}
}
这个程序会用Test
的方法产生输出,其中会有get_Name
和set_Name
- getter和setters我在说。
根据我的理解,如果 getters 和 setter 被创建 "behind the scenes" 那么也应该从 which/to 创建一个支持字段,其中 getters 和setter get/set 值。
因此,根据前面的示例,我可以使用反射来检查 Test class 的字段,例如:
static void Main(string[] args)
{
Type type = typeof(Test);
foreach (var item in type.GetFields())
{
Console.WriteLine(item.Name);
}
}
这个程序的输出是空的,我假设这是因为创建的支持字段具有 private
访问权限,所以我们看不到它。但是因为我不知道如何检查它,你能告诉我是否总是创建一个支持字段(即使我们有一个简单的 属性 只有 get;
和 set;
) ?
如果您指的是像这样的简单属性:
{get;set;}
或:
{get;}
那么是的,有一个字段;将 BindingFlags.NonPublic | BindingFlags.Instance
添加到您的 GetFields()
调用中,您会看到它:
foreach (var item in type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
{
Console.WriteLine(item.Name);
}
它通常有一个不可发音的名字,涉及 <>
- 你的名字在我的机器上是 <Name>k__BackingField
- 但是:这个名字是一个编译器特性(尽管很多序列化等库都使用它,所以不太可能改变)。
但是:不,属性本身 并不总是涉及字段;例如:
public int Value => 42; // no field
或
public int Name { get { return obj.Name; } set { obj.Name = value; } }
But since I don't know how to check it, can you please let me know if a backup field always get created (even if we have a simple property with only get; and set; ?
自动实现属性,例如
public int ReadWriteProperty { get; set; }
public int ReadOnlyProperty { get; }
确实总是会有一个由编译器生成的支持字段。但是,如果您提供自己的 getter/setter 实现,则编译器不会生成字段:
public int Zero => 0;
public int IgnoresSetter
{
get { return 10; }
set { /* Meh. Whatever you say, I'm still going to return 10 in the getter... */ }
}
这些都不会导致生成字段。