字段(C# 编程指南)

字段是在结构中直接声明的任意类型的变量。 字段是其包含类型的成员。

类或结构可能具有实例字段和/或静态字段。 实例字段特定于类型的实例。 如果你有包含实例字段 F 的类 T,则可以创建两个类型为 T 的对象并修改每个对象中 F 的值,而不会影响另一个对象中的值。 与此相比,静态字段属于类型本身,并在该类型的所有实例之间共享。 只能使用类型名称访问静态字段。 如果按实例名称访问静态字段,将出现 CS0176 编译时错误。

通常,应为字段声明 privateprotected 可访问性。 类型向客户端代码公开的数据应通过方法属性索引器提供。 通过使用这些构造间接访问内部字段,可以防止出现无效的输入值。 存储由公共属性公开的数据的私有字段称为后备存储或支持字段。 可以声明 public 字段,但随后无法阻止使用你的类型的代码将该字段设置为无效值,或者以其他方式更改对象的数据。

字段通常存储必须对多个类型方法可访问且存储时间必须长于任何单个方法的生存期的数据。 例如,表示日历日期的类型可能具有三个整数字段:一个用于月、一个用于日、一个用于年。 不在单个方法作用域外使用的变量应声明为方法主体本身中的局部变量。

字段是通过指定访问级别在类或结构块中声明的,其后跟类型,再跟字段的名称。 例如:

public class CalendarEntry
{

    // private field (Located near wrapping "Date" property).
    private DateTime _date;

    // Public property exposes _date field safely.
    public DateTime Date
    {
        get
        {
            return _date;
        }
        set
        {
            // Set some reasonable boundaries for likely birth dates.
            if (value.Year > 1900 && value.Year <= DateTime.Today.Year)
            {
                _date = value;
            }
            else
            {
                throw new ArgumentOutOfRangeException("Date");
            }
        }
    }

    // public field (Generally not recommended).
    public string? Day;

    // Public method also exposes _date field safely.
    // Example call: birthday.SetDate("1975, 6, 30");
    public void SetDate(string dateString)
    {
        DateTime dt = Convert.ToDateTime(dateString);

        // Set some reasonable boundaries for likely birth dates.
        if (dt.Year > 1900 && dt.Year <= DateTime.Today.Year)
        {
            _date = dt;
        }
        else
        {
            throw new ArgumentOutOfRangeException("dateString");
        }
    }

    public TimeSpan GetTimeSpan(string dateString)
    {
        DateTime dt = Convert.ToDateTime(dateString);

        if (dt.Ticks < _date.Ticks)
        {
            return _date - dt;
        }
        else
        {
            throw new ArgumentOutOfRangeException("dateString");
        }
    }
}

若要访问实例中的字段,请在实例名称后添加一个句点,后跟字段的名称,如 instancename._fieldName 中所示。 例如:

CalendarEntry birthday = new CalendarEntry();
birthday.Day = "Saturday";

声明字段时,可以使用赋值运算符为字段指定一个初始值。 例如,若要为 Day 字段自动赋值 "Monday",则需要声明 Day,如以下示例所示:

public class CalendarDateWithInitialization
{
    public string Day = "Monday";
    //...
}

字段会在对象实例的构造函数被调用之前即刻初始化。 如果构造函数分配了字段的值,则它将覆盖在字段声明期间给定的任何值。 有关详细信息,请参阅使用构造函数

注意

字段初始化表达式不能引用其他实例字段。

可以将字段标记为 publicprivateprotectedinternalprotected internalprivate protected。 这些访问修饰符定义该类型的用户访问该字段的方式。 有关详细信息,请参阅访问修饰符

可以选择性地将字段声明为static。 静态字段可供调用方在任何时候进行调用,即使不存在任何类型的实例。 有关详细信息,请参阅静态类和静态类成员

可以将字段声明为 readonly。 只能在初始化期间或在构造函数中为只读字段赋值。 static readonly 字段类似于常量,只不过 C# 编译器在编译时不具有对静态只读字段的值的访问权限,而只有在运行时才具有访问权限。 有关详细信息,请参阅常量

可以将字段声明为 required。 必填字段必须由构造函数初始化,或者在创建对象时由对象初始值设定项初始化。 将 System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute 特性添加到初始化所有必需成员的任何构造函数声明中。

不能在同一字段上组合 required 修饰符和 readonly 修饰符。 但是,属性只能是 requiredinit

从 C# 12 开始,主构造函数参数是声明字段的替代方法。 如果类型具有必须在初始化时提供的依赖项,则可以创建提供这些依赖项的主构造函数。 可以捕获这些参数并将其用于代替类型中声明的字段。 对于 record 类型,主构造函数参数显示为公共属性。

C# 语言规范

有关详细信息,请参阅 C# 语言规范。 该语言规范是 C# 语法和用法的权威资料。

另请参阅