C#核心学习(四)面向对象--封装(3)成员属性

目录

前言

一、什么是成员属性

属性与字段的区别

属性的组成

二、成员属性的作用

1. 数据保护与验证

2. 计算型属性

3. 延迟加载(Lazy Initialization)

三、怎么进行申明

1. 完整属性声明

2. 自动属性(Auto-Property)

3. 只读属性

四、属性的使用规则与最佳实践

1. 优先使用属性的场景

2. 命名规范

3. 性能注意事项

4. 初始化方式


前言

        在面向对象编程中,封装是保障代码健壮性和可维护性的核心原则之一。C#的成员属性(Property)作为实现封装的关键工具,通过统一的数据访问接口,解决了直接操作字段带来的风险与局限性。

        成员属性的核心价值在于

  1. ​可控的数据访问:通过 get 和 set 访问器,对字段的读写行为进行逻辑控制。
  2. ​隐式验证机制:在数据赋值时自动执行校验规则(如范围检查、空值处理)。
  3. ​灵活的扩展能力:支持动态计算值、延迟加载资源等场景,避免冗余代码。

        本文将以实用性为导向,系统讲解成员属性的本质、声明方式、典型应用场景及最佳实践,并通过完整的代码案例展示如何通过属性构建安全可靠的类结构。无论您是希望理解基础概念,还是寻求优化现有代码的方案,都能在此找到清晰的答案。

一、什么是成员属性

                        成员属性(Property)​ 是C#中一种特殊的类成员,它结合了字段(Field)和方法(Method)的特性,用于对类或结构体中的字段进行安全访问逻辑控制。通过属性,开发者可以对外暴露数据访问的接口,同时隐藏内部实现细节,从而实现面向对象编程中的封装性

属性与字段的区别

  • 字段(Field)​:直接存储数据的变量,通常为private,不直接对外暴露。
  • 属性(Property)​:通过getset访问器间接操作字段,可添加逻辑验证。

属性的组成

  • get访问器:读取属性值时调用。
  • set访问器:设置属性值时调用(可省略实现只读属性)。
  • 支持自动属性:简化只进行简单赋值的场景。
public class Person
{
    private string _name; // 字段

    // 属性
    public string Name 
    {
        get { return _name; }
        set { _name = value; }
    }
}

基本概念
1.用于保护成员变量
2.为成员属性的获取和赋值添加逻辑处理
3.解决3p的局限性
public 外部访问
private 内部访问
protected 内部和子部访问
属性可以让成员变量在外部
只能获取 不能修改 或 只能修改 不能获取 

二、成员属性的作用

1. 数据保护与验证

        通过属性对字段赋值时,可以添加有效性验证,避免非法数据。

public class Person
{
    private int _age;

    public int Age
    {
        get { return _age; }
        set 
        {
            if (value < 0)
                throw new ArgumentException("年龄不能为负数!");
            _age = value;
        }
    }
}

2. 计算型属性

        返回通过计算得到的值,而非直接存储的字段。

public class Rectangle
{
    public double Width { get; set; }
    public double Height { get; set; }

    // 计算面积(无set访问器)
    public double Area 
    {
        get { return Width * Height; }
    }
}

3. 延迟加载(Lazy Initialization)

        在首次访问时初始化资源,优化性能。

public class DataLoader
{
    private List _data;

    public List Data
    {
        get 
        {
            if (_data == null)
                _data = LoadDataFromDatabase();
            return _data;
        }
    }
}

三、怎么进行申明

1. 完整属性声明

        包含显式定义的字段和访问器逻辑。

private string _title;

public string Title
{
    get { return _title.ToUpper(); } // 返回大写形式
    set { _title = value.Trim(); }    // 存储时去除空格
}

2. 自动属性(Auto-Property)

        编译器自动生成隐藏的字段,适用于简单场景。

public string Name { get; set; } // 自动生成私有字段

3. 只读属性

  • 初始化后不可修改:通过init关键字(C# 9.0+)。
  • 运行时只读:省略set访问器。
public class Config
{
    // 只能在构造函数或初始化器中赋值
    public string Environment { get; init; } 

    // 只能在类内部修改
    public int MaxConnections { get; private set; } 
}

四、属性的使用规则与最佳实践

1. 优先使用属性的场景

  • 需要数据验证格式转换时。
  • 需要控制访问权限​(如只读、私有设置)。
  • 暴露给其他程序集的API接口。

2. 命名规范

  • Pascal命名法:首字母大写,如CustomerName
  • 逻辑分组:相关属性集中定义,提高可读性。

3. 性能注意事项

  • 避免复杂逻辑:属性访问应快速完成,避免耗时操作。
  • 缓存结果:计算密集型操作建议缓存结果

4. 初始化方式

  • 自动属性初始化:可直接赋值。
public string Status { get; set; } = "Active";
  • 只读属性初始化:通过构造函数或初始化器。
public class Product
{
    public string Sku { get; }

    public Product(string sku)
    {
        Sku = sku; // 构造函数中赋值
    }
}

附示例:

public class Book
{
    // 私有字段
    private string _title;
    private string _author;
    private decimal _price;

    // 属性封装字段(添加验证逻辑)
    public string Title
    {
        get { return _title; }
        set 
        { 
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("书名不能为空!");
            _title = value.Trim();
        }
    }

    public string Author
    {
        get { return _author; }
        set 
        { 
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("作者名不能为空!");
            _author = value.Trim();
        }
    }

    public decimal Price
    {
        get { return _price; }
        set 
        { 
            if (value < 0)
                throw new ArgumentException("价格不能为负数!");
            _price = value;
        }
    }

    // 计算型属性(折扣价)
    public decimal DiscountPrice 
    {
        get { return _price * 0.9m; } // 打九折
    }
}

使用:

class Program
{
    static void Main()
    {
        // 创建图书列表
        List books = new List();

        // 使用对象初始化器添加图书
        books.Add(new Book 
        {
            Title = "C# 编程指南",
            Author = "李华",
            Price = 50.0m
        });

        books.Add(new Book 
        {
            Title = ".NET 设计模式",
            Author = "王强",
            Price = 80.0m
        });

        // 遍历查找价格低于 70 的图书(使用传统循环和条件)
        Console.WriteLine("价格低于 70 的图书:");
        foreach (Book book in books)
        {
            if (book.Price < 70)
            {
                Console.WriteLine($"{book.Title} ({book.Author})");
                Console.WriteLine($"原价: {book.Price},折扣价: {book.DiscountPrice}");
            }
        }
    }
}

你可能感兴趣的:(学习,c#,成员属性)