一、字段 和 属性 终极区别(默写简答题)
核心口诀:字段存数据,属性做管控
-
使用场景不同:字段一般用于类内部使用;属性专门对外公开,供外部类读写数据
-
访问权限不同:字段默认 private(私有);属性基本都是 public(公共)
-
功能结构不同 :字段就是普通变量,仅用于存储数据;属性自带 get、set 访问器,可做数据拦截、校验
-
本质区别 :字段负责存储数据,属性不存数据,只负责读写拦截、逻辑校验
二、get / set 访问器 核心原理(必考)
1. 触发规则(对应你的代码)
-
赋值时触发 set 访问器 :
p.Name = "T" -
取值时触发 get 访问器 :
Console.WriteLine(p.Name)
2. 关键字含义
-
get :读取访问器,必须
return关联私有字段的值 -
set :赋值访问器,value 代表外部传入的赋值数据
3. 核心作用
属性可以在 set 中做数据校验、过滤、限制非法值,弥补字段直接赋值无校验的漏洞。
示例:你的代码禁止空字符串赋值
set{
Console.WriteLine("set访问器触发了"+value);
if (value.Length==0)
{
throw new Exception("不能赋空字符串");
}
_name = value;
}
三、C# 三种属性完整写法(全覆盖)
写法1:完整属性写法(最原始、可自由写逻辑)
适用:需要复杂校验、拦截逻辑
//1.先定义私有字段
private string _name;
//2.定义公共属性
public string Name
{
get{
Console.WriteLine("get访问器触发了");
return _name;
}
set{
Console.WriteLine("set访问器触发了"+value);
if (value.Length==0)
{
throw new Exception("不能赋空字符串");
}
_name = value;
}
}
写法2:简写属性(Lambda 表达式写法)
适用:逻辑简单,无需复杂校验,精简代码
private int _a1;
public int A1 { get => _a1; set => _a1 = value; }
写法3:自动属性(语法糖写法、项目最常用)
适用:不需要任何拦截逻辑,纯读写数据
编译器会自动帮我们生成隐藏私有字段,无需手动声明
// 带默认值的自动属性
public string Id { get; set; } = "001";
四、只读属性(重点考点)
1. 定义规则
只写 get 、不写 set,属性变为只读属性
外部只能读取,无法赋值修改
2. 你的代码示例
public string Msg { get; }
报错场景:
p3.Msg = "S"; // 报错!只读属性不能赋值
五、代码执行流程解析
People p = new People();
p.Name = "T"; // 赋值 → 触发 set 访问器
Console.WriteLine(p.Name); // 取值 → 触发 get 访问器
People p3 = new People();
p3.Name = "Y";
Console.WriteLine(p3.Name+":"+p3.Id);
每一个对象的属性都是独立数据,互不干扰。
六、终极考点总结(背诵)
-
字段存数据,属性控读写
-
外部赋值触发 set,外部取值触发 get
-
value 是 set 专属关键字,代表外部传入的值
-
自动属性:系统自动生成隐藏字段,最简写法,项目首选
-
只有get没有set → 只读属性,禁止赋值
-
属性最大优势:可以在set中做数据校验,保证数据安全
------------属性拦截例子(get动态计算 + set数据校验)------------
一、代码核心功能概述
本案例演示 属性 get/set 拦截的两大核心用法
-
set 拦截:对外部传入的数据做合法性校验,非法数据直接抛异常,保护数据安全
-
get 拦截:取值时动态加工数据,不直接返回原值,实现动态计算效果
二、年龄属性 Age 逐行精讲(高频考点)
1. 底层字段
private int _age;
私有字段,专门用于存储真实年龄数据,外部无法直接访问。
2. set 赋值拦截(数据校验)
set
{
if (value < 0||value>20)
{
throw new Exception("年龄不在合适的范围内");
}
_age = value;
}
校验规则 :年龄只能在 0~20 之间
非法场景:赋值负数、大于20的数字 → 直接抛出程序异常,阻止非法数据存入字段
合法场景:赋值 0-20 数值 → 正常给私有字段 _age 赋值
3. get 取值拦截(动态计算)
get
{
_age *= 10;
return _age;
}
超级重点(易错坑)
每次读取 Age 属性,都会执行一次:原值 * 10 ,并且修改底层字段真实值
4. 执行流程拆解(你的代码运行过程)
d1.Age = 19; // set触发:19合法,_age = 19
Console.WriteLine(d1.Age); // get触发:_age = 19*10 = 190,输出190
如果多次取值,会叠加翻倍(每读一次 ×10)
三、颜色属性 Color 精讲(集合匹配校验)
1. 预设合法数据
private char[] colors = { '黄', '白', '黑' };
规定:狗狗颜色只能是黄、白、黑三种
2. 颜色校验逻辑
set
{
if (!colors.Contains(value))
{
throw new Exception("颜色不合适");
}
_color = value;
}
逻辑:判断用户赋值的颜色 是否不在合法数组中
不匹配 → 抛异常拦截;匹配 → 正常存入字段
3. 正常运行代码
d1.Color = '白'; // 合法
Console.WriteLine(d1.Color);
四、public int a=100; 易错对比
public int a=100;
这是 公共字段,不是属性!
无 get、无 set、无任何拦截、无校验,外部可以随意赋值负数、乱值,数据不安全。
对比结论:字段直接暴露不安全,属性封装可校验、可管控。
五、本题两大核心考点(考试必考)
1. set 访问器作用
对外部赋值的数据进行过滤、校验、限制,保证类内部数据的合法性与安全性。
2. get 访问器作用
可以对原始数据二次加工、动态计算、格式转换后再返回给外部,不改变外部赋值逻辑。
六、超级易错坑点(必背)
-
get 里面如果修改字段值,会永久改变底层数据,每次读取都会叠加效果
-
set 中 value 是固定关键字,代表外部赋进来的值
-
字段公开直接赋值无校验,属性可以精准拦截非法数据
-
Contains() 可以判断值是否存在于数组/集合中,常用于固定范围校验
七、简答题满分总结
为什么要用属性封装字段?
为了保证数据安全,通过 set 访问器可以对赋值数据进行合法性校验,拦截非法数据;通过 get 访问器可以对返回数据进行动态加工处理,同时隐藏私有字段,符合面向对象封装特性。