🐸 青蛙编程网
首页 / C# / 面向对象 / 2. 属性与方法

属性与方法

这是什么:属性(property)——长得像字段、实则是一对 get/set 方法的"带门卫的字段"。

为什么用:上一章用 public string Name 存名字——能用,但有个隐患:外面可以随便 d.Age = -5,哪有负几岁的狗?属性就是给数据装的门卫,坏数据进不来。

如何用:本章先给 Dog 加一个自动属性,再把 Age 改成带校验的完整属性,试试负数还能不能塞进去。

属性:带门卫的字段

属性长得像字段,其实是一对方法:get 管"读",set 管"写",数据进出都要过门卫。

Dog d = new Dog { Name = "旺财" };   // 对象初始化器:一行喂多个属性
d.Age = -5;                          // 想搞破坏?没门
Console.WriteLine($"{d.Name} 今年 {d.Age} 岁");

class Dog
{
    public string Name { get; set; }   // 自动属性:不需要检查,一行搞定

    private int age;                   // 真正存数据的字段,private 锁起来
    public int Age                     // 属性:读写都过门卫
    {
        get { return age; }
        set
        {
            if (value < 0) value = 0;  // value 代表"别人塞进来的值"
            age = value;
        }
    }
}

运行输出:

旺财 今年 0 岁

-5 被门卫拦下改成 0。这就是属性的价值:数据不是想塞就塞,得先过检查。

写法 什么时候用
{ get; set; } 自动属性 读写不需要检查(大多数情况)
完整 get / set 读写要加校验、联动等规则
只有 get; 只许读不许改,比如编号

和 Java 对比:少写一半

Java 里要手写一对 getter/setter,用的时候也是调方法:

d.setName("旺财");                  // Java:调方法
System.out.println(d.getName());

C# 直接用属性,像访问字段一样自然:

d.Name = "旺财";                    // 看着是赋值,实际走 set
Console.WriteLine(d.Name);          // 看着是读字段,实际走 get

写起来短,改起来灵活:哪天要加校验,只改属性内部,用它的一百行代码一个字都不用动。

方法与表达式体成员

方法还是老写法,但只有一行时可以缩成"表达式体":用 => 直接给结果。

class Dog
{
    public string Name { get; set; }
    public int Age { get; set; }

    public void Bark()                // 普通写法
    {
        Console.WriteLine($"{Name}:汪汪!");
    }

    public void Wag() => Console.WriteLine($"{Name} 疯狂摇尾巴");  // 表达式体
    public string Info => $"{Name}({Age}岁)";   // 只读属性也能这么写
}

Wag() 和 Info 都是一行,=> 后面直接就是内容。以后在别人代码里见到 => 别慌——展开大括号就是你熟悉的写法。

记忆口诀

字段裸奔要出事,属性把门 get set 拦;一行方法打个箭头,代码瘦身看得见。

动手改

  1. 给 Age 的 set 再加一条规则:超过 30 也不行,按 30 算
  2. 写一个只读属性 Description,返回"XX 是一只 X 岁的狗"并打印
  3. 把 Bark() 改成表达式体写法,运行验证输出没变

下一章:继承与多态,让代码代代相传 🐸

📥 下载本章代码

ZIP 内含本章全部代码文件与说明,解压即用,与教程内容同步生成。