想象你在开一家玩具工厂:
C#代码示例:
// 1. 设计模具(类)
public class 变形金刚
{
// 玩具属性(特征)
public string 名字 { get; set; }
public string 颜色 { get; set; }
// 玩具功能(方法)
public void 变形()
{
Console.WriteLine($"{名字}开始变形!咔嚓咔嚓...");
}
}
// 2. 生产玩具(对象)
var 擎天柱 = new 变形金刚 { 名字 = "擎天柱", 颜色 = "红色" };
var 大黄蜂 = new 变形金刚 { 名字 = "大黄蜂", 颜色 = "黄色" };
// 3. 使用功能
擎天柱.变形(); // 输出:擎天柱开始变形!咔嚓咔嚓...
public class 电饭煲
{
private int _温度; // 隐藏内部零件
// 公共按钮
public void 开始煮饭()
{
_加热();
Console.WriteLine("饭好了");
}
private void _加热() // 内部逻辑
{
_温度 = 100;
}
}
public class 汽车
{
public void 启动() => Console.WriteLine("轰隆隆...");
}
public class 电动车 : 汽车 // 继承
{
public void 充电() => Console.WriteLine("滋滋滋...");
}
var 特斯拉 = new 电动车();
特斯拉.启动(); // 继承自汽车
特斯拉.充电(); // 自己的新功能
public class 设备
{
public virtual void 开启() => Console.WriteLine("设备启动");
}
public class 空调 : 设备
{
public override void 开启() => Console.WriteLine("空调制冷❄️");
}
设备 我的设备 = new 空调();
我的设备.开启(); // 输出:空调制冷❄️(实际调用子类方法)
public abstract class 电器
{
public abstract void 开关(); // 抽象方法(无具体实现)
}
public class 风扇 : 电器
{
public override void 开关() => Console.WriteLine("风扇转动");
}
工具 | 作用 | 示例 |
---|---|---|
属性 | 控制字段访问(get/set) | public int Age { get; private set; } |
接口 | 强制实现指定功能 | interface I飞行 { void 飞(); } |
结构体 | 轻量级对象(适合小数据) | public struct 坐标 { public int X, Y; } |
泛型 | 可适配多种类型的模具 | public class 盒子 |
接口示例:
public interface I攻击
{
void 攻击();
}
public class 激光枪 : I攻击
{
public void 攻击() => Console.WriteLine("biu biu biu~");
}
C# OOP就是把程序变成「智能玩具工厂」:
试试这个例子:
public class 猫咪
{
public string 名字 { get; set; }
public virtual void 叫() => Console.WriteLine("喵~");
}
public class 布偶猫 : 猫咪
{
public override void 叫() => Console.WriteLine("优雅的喵~");
}
猫咪 猫1 = new 猫咪 { 名字 = "橘座" };
猫咪 猫2 = new 布偶猫 { 名字 = "仙女" };
猫1.叫(); // 输出:喵~
猫2.叫(); // 输出:优雅的喵~
想象你在一个超大城市送快递:
人民路15号
(全城可能有100个同名地址)北京市.朝阳区.人民路15号
vs 上海市.黄浦区.人民路15号
C#示例:
// 不同命名空间的同名类
namespace 北京分公司
{
class 员工 { public string 姓名 = "张三"; }
}
namespace 上海分公司
{
class 员工 { public string 姓名 = "李四"; }
}
// 使用时明确指明"行政区"
var 北京员工 = new 北京分公司.员工();
var 上海员工 = new 上海分公司.员工();
场景 | 无命名空间 | 有命名空间 |
---|---|---|
类名冲突 | ❌ 编译报错 | ✅ 公司A.类 vs 公司B.类 |
代码组织 | 所有类堆在一起 | 按功能/模块分层归类 |
团队协作 | 需人工加前缀XX_类名 |
天然隔离(如部门A.报表工具 ) |
using System; // 基础服务(如Console)
using System.IO; // 文件读写
using System.Threading; // 多线程
using UnityEngine; // Unity游戏开发
文件示例:
// 文件:北京市/朝阳区/人民路.cs
namespace 北京市.朝阳区
{
public class 人民路 { /*...*/ }
}
默认隐藏机制
// 需要手动"开地图"
using 北京分公司;
var 员工 = new 员工(); // 自动找北京分公司下的类
嵌套命名空间
namespace 集团.研发部.CSharp组
{
class 代码生成器 { /*...*/ }
}
别名解决重名
using 北京员工 = 北京分公司.员工;
using 上海员工 = 上海分公司.员工;
不同公司的SDK共存
using 阿里云.存储;
using 腾讯云.数据库;
Unity插件隔离
namespace MyGame.Plugins.AI
{
class 行为树 { /*...*/ }
}
内部模块划分
namespace 电商系统
{
namespace 订单模块 { /*...*/ }
namespace 支付模块 { /*...*/ }
}
类名污染
→ 就像不能有同名身份证号System.IO.File
就知道是文件操作 终极口诀
命名空间是代码的户籍系统,让张三
可以存在于北京/上海/深圳
而不冲突!
试试这个例子:
namespace 学校A
{
class 学生 { public string 名字 = "小明"; }
}
namespace 学校B
{
class 学生 { public string 名字 = "小红"; }
}
// 使用
var 学生1 = new 学校A.学生();
var 学生2 = new 学校B.学生();
Console.WriteLine(学生1.名字); // 输出"小明"
控制代码的「可见度」就像调节房间的隐私级别
关键字 | 权限范围 | 现实比喻 |
---|---|---|
public |
完全公开(所有代码可访问) | 公园长椅(谁都能坐) |
private |
仅当前类内部可用 | 日记本(仅自己看) |
protected |
当前类及子类可用 | 家族相册(自己和子女能看) |
internal |
同一程序集(项目)内可用 | 公司内网(只有员工能访问) |
protected internal |
protected + internal 的并集 |
公司员工及其外包团队 |
private protected |
当前类及同一程序集中的子类 | 家族企业核心机密(限家族员工) |
示例:
class 家庭相册
{
public string 全家福 = "公开照片"; // 所有人可见
private string 私房钱位置 = "床底下"; // 仅本类可见
protected string 祖传秘方 = "红烧肉配方"; // 子女可见
}
关键字 | 适用场景 | 示例 |
---|---|---|
public |
可被其他程序集引用 | public class 工具类 { } |
internal |
仅当前项目可用(默认) | internal struct 坐标 { } |
abstract |
抽象类(不能实例化) | public abstract class 动物 { } |
sealed |
密封类(禁止继承) | public sealed class 字符串工具 { } |
关键字 | 作用 | 示例 |
---|---|---|
readonly |
字段只能在构造函数中修改 | public readonly int ID = 1; |
const |
编译时常量(完全不可变) | public const float PI = 3.14f; |
static |
属于类而非实例 | public static int 计数器 = 0; |
partial |
拆分类定义到多个文件 | public partial |