- 字段和属性,都是成员变量,都用于存取数据。
- 字段读写无限制,属性通过get和set方法可以控制读写(比如可以在年龄Age属性的set方法中限制,当赋值的value大于200时,则赋值默认值100,从而确保数据准确性)。
- 按照类的设计原则,字段一般用在类的内部使用(private),属性一般供外部类访问(public)。
示例类
cs
public class TestClass
{
//私有字段
private string privateField;
//公有字段(实际开发时,存在公有的字段)
public string publicField;
//静态字段
public static string staticField;
//私有属性
private string privateProp { get; set; }
//公有属性
public string publicProp { get; set; }
//静态属性
public static string staticProp { get; set; }
//重写ToString方法
public override string ToString()
{
return $"privateField:{privateField},publicField:{publicField},staticField:{staticField},privateProp:{privateProp},publicProp:{publicProp},staticProp:{staticProp}";
}
}
使用System.Reflection反射验证
cs
public string GetName()
{
string infoStr = string.Join(",", typeof(TestClass).GetFields().Select(s => s.Name));
string propStr = string.Join(",", typeof(TestClass).GetProperties().Select(s => s.Name));
return $"{infoStr} || {propStr}";
}
// 等价于
public string GetName()
{
//BindingFlags绑定Public(公有)、Instance(实例)、Static(静态)
string infoStr = string.Join(",",
typeof(TestClass).GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
.Select(s => s.Name));
string propStr = string.Join(",",
typeof(TestClass).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
.Select(s => s.Name));
return $"{infoStr} || {propStr}";
}
结果为:publicField,staticField || publicProp,staticProp
使用System.Reflection的GetFields获取类的字段信息,使用GetProperties获取类的属性信息,默认获取Public(公有)、Instance(实例)、Static(静态)的变量
加上BindingFlags.NonPublic条件获取会得到以下结果
cs
string infoStr = string.Join(",",
typeof(TestClass).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
.Select(s => s.Name));
string propStr = string.Join(",",
typeof(TestClass).GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
.Select(s => s.Name));
infoStr为:privateField,publicField,<privateProp>k__BackingField,<publicProp>k__BackingField,staticField,<staticProp>k__BackingField
propStr为:privateProp,publicProp,staticProp
propStr的值是预期之内的,多加了BindingFlags.NonPublic条件,就多获取到私有的privateProp属性。
infoStr的值却意料之外,除了多了privateField私有字段,还多了几个名字带有属性名的
k__
BackingField字段。
在C#中,k__BackingField
是一个常见的编译器生成的字段名称,它用于实现属性的自动属性(auto-implemented properties)。
在C#中,自动属性允许你声明一个属性而不显式定义后备字段。编译器会自动为你创建一个私有的后备字段,并为你提供getter和setter的默认实现。这个自动创建的后备字段的名称通常以k__BackingField
结尾。
例如,考虑以下代码:
cs
public class MyClass
{
public int MyProperty { get; set; }
}
编译器实际上会为你生成如下的代码:
cs
public class MyClass
{
private int <MyProperty>k__BackingField;
public int MyProperty
{
get
{
return <MyProperty>k__BackingField;
}
set
{
<MyProperty>k__BackingField = value;
}
}
}
注意,<MyProperty>k__BackingField
是编译器生成的字段名称。在实际代码中,你不应该直接访问这个字段,因为它是一个实现细节,可能会在不同的编译器版本或不同的编译器设置下发生变化。