C#入门概念理解

🧩 C#面向对象编程(OOP)→ “智能玩具工厂”

1. 核心思想:用「对象」组装程序

想象你在开一家玩具工厂

设计模具(类)→ 比如”变形金刚模具”
生产玩具(对象)→ 用模具造出100个变形金刚
玩具自带功能(方法)→ 能变形、能发光

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("风扇转动🌀");
}

🏭 C#特色OOP工具

工具 作用 示例
属性 控制字段访问(get/set) public int Age { get; private set; }
接口 强制实现指定功能 interface I飞行 { void 飞(); }
结构体 轻量级对象(适合小数据) public struct 坐标 { public int X, Y; }
泛型 可适配多种类型的模具 public class 盒子<T> { public T 内容; }

接口示例

public interface I攻击 
{
    void 攻击();
}
 
public class 激光枪 : I攻击 
{
    public void 攻击() => Console.WriteLine("biu biu biu~");
}

💡 为什么用C# OOP?

像工厂流水线一样组织代码 → 复杂系统变清晰
避免重复代码 → 相同功能通过继承复用
轻松维护 → 修改一个类不影响其他模块

🚀 终极总结

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.叫(); // 输出:优雅的喵~

🌐 命名空间(Namespace)→ 编程的「行政区划」

1. 最简理解(快递地址系统)

想象你在一个超大城市送快递:

没有命名空间:所有地址都是人民路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.名字); // 输出"小明" 

📜 C#访问管理关键字大全(极简版)

控制代码的「可见度」就像调节房间的隐私级别

1. 成员访问控制
关键字 权限范围 现实比喻
public 完全公开(所有代码可访问) 公园长椅(谁都能坐)
private 仅当前类内部可用 日记本(仅自己看)
protected 当前类及子类可用 家族相册(自己和子女能看)
internal 同一程序集(项目)内可用 公司内网(只有员工能访问)
protected internal protected + internal的并集 公司员工及其外包团队
private protected 当前类及同一程序集中的子类 家族企业核心机密(限家族员工)

示例

class 家庭相册 
{
    public string 全家福 = "公开照片";      // 所有人可见 
    private string 私房钱位置 = "床底下";   // 仅本类可见 
    protected string 祖传秘方 = "红烧肉配方"; // 子女可见 
}
2. 类/结构体访问控制
关键字 适用场景 示例
public 可被其他程序集引用 public class 工具类 { }
internal 仅当前项目可用(默认) internal struct 坐标 { }
abstract 抽象类(不能实例化) public abstract class 动物 { }
sealed 密封类(禁止继承) public sealed class 字符串工具 { }
3. 特殊访问场景
关键字 作用 示例
readonly 字段只能在构造函数中修改 public readonly int ID = 1;
const 编译时常量(完全不可变) public const float PI = 3.14f;
static 属于类而非实例 public static int 计数器 = 0;
partial 拆分类定义到多个文件 public partial class 大文件 { }

⚡ 黄金搭配组合

数据保护三件套

private string _密码;  // 字段私有化 
public string 密码 { get; private set; } // 外部只读 

安全继承方案

public abstract class 基类 { }  // 必须被继承 
public sealed class 最终版 : 基类 { } // 不能再被继承 

💡 访问控制的本质

通过关键字控制代码的「可触碰范围」,像给不同人发不同门禁卡:

public → 万能卡
private → 个人保险箱钥匙
protected → 家族通行证

一句话原则
默认用private,必要才放开!

 🍎 类型 → 数据的「分类标签」

现实比喻
就像水果店的分类框:

int 框放苹果(整数)
string 框放香蕉(文字)
bool 框放榴莲(只有true/false两种状态)

C#示例

int 苹果数量 = 5;            // 整数类型 
string 香蕉品牌 = "都乐";     // 字符串类型 
bool 榴莲已熟 = true;        // 布尔类型 

特点

告诉编译器这个变量能存什么数据
就像盒子上的标签,防止你把牛奶倒进装乒乓球的箱子里

🏷️ 属性 → 对象的「特征描述」

现实比喻
就像你的身份证:

姓名(字符串类型)
年龄(整数类型)
是否已婚(布尔类型)

C#示例

public class 人 
{
    // 自动属性(智能字段)
    public string 姓名 { get; set; } = "张三";
    
    // 完整属性(带逻辑控制)
    private int _年龄;
    public int 年龄 
    {
        get => _年龄;
        set => _年龄 = value > 0 ? value : 0; // 禁止负数年龄 
    }
}
 
var 我 = new 人();
我.年龄 = -5;  // 实际会被修正为0 
Console.WriteLine(我.姓名); // 输出:张三 

属性 vs 字段

字段 属性
作用 直接存储数据 控制数据的访问方式
示例 public int age; public int Age { get; set; }
优势 简单直接 可添加验证逻辑/计算逻辑

🛠️ 方法 → 对象的「行为能力」

现实比喻
就像手机的功能按钮:

打电话() → 需要输入号码(参数)
拍照() → 返回一张照片(返回值)
关机() → 不需要额外信息(无参数)

C#示例

public class 手机 
{
    // 无返回值方法 
    public void 关机() 
    {
        Console.WriteLine("正在关机...");
    }
 
    // 带参数和返回值的方法 
    public string 打电话(string 号码)
    {
        return $"正在呼叫:{号码}";
    }
}
 
var 我的手机 = new 手机();
我的手机.关机();
string 状态 = 我的手机.打电话("13800138000");

方法三要素

输入(参数):string 号码
处理:拼接字符串
输出(返回值):string类型的状态

🧩 三者的关系 → 乐高积木组合

public class 汽车  // 类型(积木模具)
{
    public string 品牌 { get; set; } // 属性(积木特征)
    
    public void 加速(int 油门力度) // 方法(积木功能)
    {
        Console.WriteLine($"{品牌}车加速{油门力度}档!");
    }
}
 
var 我的车 = new 汽车 { 品牌 = "丰田" };
我的车.加速(3);  // 输出:丰田车加速3档!

📚 对比总结表

概念 比喻 特点 示例
类型 数据分类框 决定能存什么数据 intstringbool
属性 对象特征卡 控制对特征的访问 public int Age { get; set; }
方法 对象功能按钮 通过输入得到输出 public string 呼叫(string 号码)

💡 为什么重要?

类型安全 → 防止把文字当数字计算
属性封装 → 保护数据有效性(如年龄不能为负)
方法复用 → 像手机”拍照”功能,可以反复调用

试试这个例子理解三者协作:

public class 灯泡 
{
    public bool 是否亮着 { get; private set; } // 属性 
    
    public void 开关() // 方法 
    {
        是否亮着 = !是否亮着;
        Console.WriteLine(是否亮着 ? "灯泡亮了💡" : "灯泡灭了🌑");
    }
}
 
var 客厅灯 = new 灯泡();
客厅灯.开关();  // 输出:灯泡亮了💡 

🧱 在C#中定义类(Class)→ 就像「设计一张产品说明书」

1. 最简版定义(空壳类)
public class 手机  // ← 类名 
{
    // 这里是属性和方法的存放区(目前是空的)
}

public:表示这个”说明书”可以公开使用
class:声明这是一个类(不是接口/结构体)
手机:类名(建议用帕斯卡命名法,如iPhone14

2. 完整版定义(含属性+方法)
public class 电饭煲 
{
    // 属性 → 产品参数 
    public string 品牌 { get; set; } = "美的";  // 默认值 
    public int 容量 { get; set; }  // 单位:升 
 
    // 方法 → 产品功能 
    public void 开始煮饭()
    {
        Console.WriteLine($"{品牌}电饭煲正在煮{容量}升饭...");
    }
 
    public bool 是否煮熟(int 分钟) 
    {
        return 分钟 > 30;  // 30分钟以上算煮熟 
    }
}

🛠️ 使用这个类(生产具体产品)

// 实例化对象(根据说明书造产品)
var 我家电饭煲 = new 电饭煲 
{ 
    容量 = 5  // 设置属性 
};
 
// 调用方法 
我家电饭煲.开始煮饭();  // 输出:美的电饭煲正在煮5升饭...
bool 熟了 = 我家电饭煲.是否煮熟(40);
Console.WriteLine(熟了 ? "饭熟了🍚" : "再等等⏳"); 

📝 定义类的关键要点

部分 作用 示例
类名 类型的标识符 class 学生 { }
属性 对象特征(数据) public int Age { get; set; }
方法 对象行为(功能) public void 跑() { }
构造函数 初始化对象的特殊方法 public 学生() { }

⚡ 自动生成类的快捷键(VS实用技巧)

新建类文件:Ctrl + Shift + A → 选择”类”
快速生成属性:输入 prop → 按两次Tab

public int MyProperty { get; set; }  // 自动生成 

生成构造函数:输入 ctor → 按Tab

public 电饭煲() { }  // 自动生成 

🌰 生活化类比

编程概念 现实对应物 关系说明
产品设计图纸 定义了能生产哪些产品
对象 根据图纸生产的实物 每个产品都是独立的
属性 产品参数(颜色/重量) 描述产品特征
方法 产品功能(开机/加热) 让产品执行操作

💡 为什么用类?

代码复用:一张图纸能造无数个同类产品
逻辑封装:电饭煲内部电路对用户不可见(只管按按钮)
易于维护:修改图纸即可影响所有产品

试试这个完整示例:

public class 空调 
{
    public string 型号 { get; set; } = "格力KFR-35GW";
    private int _温度 = 26;  // 私有字段 
 
    // 属性(带温度校验)
    public int 温度 
    {
        get => _温度;
        set => _温度 = (value >= 16 && value <= 30) ? value : _温度;
    }
 
    public void 制冷()
    {
        Console.WriteLine($"{型号}正在{温度}℃制冷❄️");
    }
}
 
// 使用类 
var 客厅空调 = new 空调 { 温度 = 22 };
客厅空调.制冷();  // 输出:格力KFR-35GW正在22℃制冷❄️ 

🏭 实例化 → 把「设计图」变成「实物」

1. 最简实例化(造基础款)
// 设计图 
public class 手机 
{
    public string 品牌 { get; set; }
}
 
// 生产实物 
手机 我的手机 = new 手机();  // ← 关键new操作 
我的手机.品牌 = "华为";
Console.WriteLine(我的手机.品牌);  // 输出:华为 

new:相当于工厂的「生产按钮」
手机():调用默认构造函数(隐藏的无参数构造)

🎨 进阶实例化(带个性化定制)

方式1:先造后改(流水线模式)
var 员工 = new 员工信息();
员工.姓名 = "张三";
员工.工号 = 10086;
方式2:造时即改(个性化定制)
var 员工 = new 员工信息 
{
    姓名 = "李四",  // ← 对象初始化器 
    工号 = 10010 
};
方式3:强制要求(构造函数设门槛)
public class 订单 
{
    public 订单(string 订单号)  // 带参数的构造 
    {
        this.订单号 = 订单号;
    }
    public string 订单号 { get; }
}
 
// 必须提供订单号才能创建 
var 订单 = new 订单("DD20230729"); 

⚡ 内存角度理解(超重要!)

手机 a = new 手机();  // 在堆内存开房间 
手机 b = a;          // b拿到a的房间钥匙(指向同一对象)
a.品牌 = "苹果";
Console.WriteLine(b.品牌);  // 输出:苹果(因为改的是同一个房间)
操作 内存表现 类比
new 手机() 在堆内存分配新空间 开发商新建一栋房
b = a 复制钥匙(引用传递) 给你同一栋房的钥匙

🛠️ 实例化的5个关键细节

必须用new(值类型除外)

// 错误示范 
手机 坏例子;  // 只声明未实例化 
坏例子.品牌 = "小米";  // ❌ 运行时报错!

构造函数是「出厂设置」

public class 学生 
{
    public 学生()  // 构造函数 
    {
        Console.WriteLine("新生入学");
    }
}

可以批量生产

手机[] 仓库 = new 手机[100];  // 准备100个位置 
仓库[0] = new 手机();        // 第一个位置放手机 

var让代码更简洁

var 实例 = new 复杂类名();  // 自动推断类型 

实例化时内存自动回收

{
    var 临时 = new 对象();  // 进入作用域时分配内存 
} // 离开作用域后,内存会被GC自动回收 

🌰 现实场景类比

编程操作 现实对应
new 手机() 工厂组装一台新手机
手机 备用机 = 主用机 把手机借给朋友用(同一台设备)
手机 新机 = new 手机() 买一台全新手机

💡 为什么需要实例化?

图纸≠实物:设计图不能直接打电话,必须造出手机
独立存储:每个对象有独立的内存空间(如不同玩家的游戏角色)
动态创建:运行时按需生产对象(如电商下单才生成订单)

🚀 终极口诀
new一下,内存划,构造函数做初始化,从此对象可调用!

试试这个例子:

public class 灯泡 
{
    public bool 是否亮着 { get; set; }
    public void 切换状态() => 是否亮着 = !是否亮着;
}
 
var 客厅灯 = new 灯泡();
客厅灯.切换状态();
Console.WriteLine(客厅灯.是否亮着 ? "灯亮了💡" : "灯灭了🌑");

🗝️ C#关键字 → 编程语言的「交通信号灯」

1. 基础关键字(红绿灯级别)
关键字 作用 通俗比喻
if 条件判断 岔路口指示牌:”如果下雨→走左边”
for 循环执行 洗衣机定时器:”转5圈后停止”
using 自动释放资源 快递柜取件:用完自动关门
try-catch 错误处理 防摔手机壳:摔了也不碎屏

示例

if (下雨了) 
{
    Console.WriteLine("带伞☔"); 
}
else 
{
    Console.WriteLine("戴墨镜😎");
}

🏗️ 类型相关(建筑工具)

关键字 作用 现实类比
class 定义类 建筑设计图
struct 定义结构体 简易帐篷图纸(比房子轻量)
enum 枚举类型 菜单编号(1.咖啡 2.茶)
interface 定义接口 USB标准:只要符合就能插

示例

enum 饮料 { 可乐, 雪碧, 橙汁 }
饮料 我的选择 = 饮料.橙汁;

🔐 访问控制(权限管理)

关键字 作用 类比
public 完全公开 公园长椅(谁都能坐)
private 仅内部可用 日记本(仅自己看)
protected 家族传承 祖传秘方(只传子女)
internal 公司内部使用 员工食堂(外人不能进)

示例

class 银行账户 
{
    private decimal _余额;  // 私密金库 
    public void 存钱(decimal 金额) { _余额 += 金额; }  // 公开操作口 
}

⚡ 高级特性(黑科技)

关键字 作用 类比
async 异步执行 外卖订单:下单后不用等送达
await 等待异步完成 等快递时刷手机
delegate 委托(函数指针) 代金券:凭券兑换服务
event 事件机制 门铃:按铃触发通知

示例

async Task 煮面()
{
    await 烧水();  // 等水开时不用傻等 
    Console.WriteLine("下面🍜"); 
}

📌 特殊标记(便利贴)

关键字 作用 类比
var 自动推断类型 盲盒:拆开才知道是啥
const 定义常量 刻石碑:内容永不变
readonly 运行时常量 纹身:纹完后不能改
nameof 获取变量名 点名册:防止写错名字

示例

const int 最大尝试次数 = 3;
Console.WriteLine($"请检查{nameof(最大尝试次数)}"); // 输出"最大尝试次数"

💡 为什么记关键字?

避免冲突:这些词不能用作变量名(像不能给孩子取名”法律”)
提高效率:VS智能提示依赖关键字识别
理解框架:ASP.NET等框架大量使用async/await等特性

🚀 速记口诀
if判断for循环,class造对象,public开门private藏,async让你不卡顿!

试试这个综合例子:

public class 智能家居 
{
    private bool _灯开关 = false;
    
    public void 切换灯光() 
    {
        _灯开关 = !_灯开关;
        Console.WriteLine(_灯开关 ? "灯亮了💡" : "灯灭了🌑");
    }
}
 
var 我家 = new 智能家居();
for (int i = 0; i < 3; i++) 
{
    我家.切换灯光();  // 灯会闪三次 
}

🎁 数据类型 → 数据的「分类收纳盒」

1. 最简理解(超市储物柜版)

想象超市的储物柜有三种格子:

整数型柜子 → 只能放1、2、3这类完整数字
小数型柜子 → 专放3.14、0.5这类带小数点的
文字型柜子 → 只收"你好"、“ABC”`这类文本

C#示例

int 苹果数量 = 5;           // 整数柜子 
double 苹果价格 = 3.5;       // 小数柜子 
string 标语 = "新鲜水果";    // 文字柜子 

📦 为什么需要数据类型?

防止乱放东西

❌ 错误:把文字塞进数字柜 → int 年龄 = "二十五";
✅ 正确:int 年龄 = 25;

节省空间

bool型(true/false)只要1比特,而int占32比特

便于计算

数字能加减乘除,文字能拼接但不可计算

🧩 常用数据类型(8大基础款)

类型 能装什么 例子 容量
int 整数 -100099 ±21亿
double 小数 3.14-0.5 15位精度
decimal 高精度小数(钱) 99.99m 28位精度
bool 是非判断 truefalse 1比特
char 单个字符 'A''好' 2字节
string 文本串 "Hello" 最大1GB
byte 二进制数据(像素/文件) 0xFF 0~255
DateTime 日期时间 DateTime.Now 0001~9999年

🌰 生活场景类比

场景 适合的数据类型 代码示例
计算学生年龄 int int 年龄 = 18;
记录商品价格 decimal decimal 价格 = 9.9m;
判断是否登录 bool bool 已登录 = true;
存储用户昵称 string string 昵称 = "喵星人";
处理图片像素 byte byte 红色 = 0xFF;

⚠️ 新手常见坑

小数陷阱

double a = 0.1 + 0.2;  // 实际=0.30000000000000004 
decimal b = 0.1m + 0.2m; // 正确做法(金融计算用decimal)

char vs string

char 字母 = 'A';     // ✅ 单引号单字符 
string 单词 = "A";   // ✅ 双引号可多字符 
// char 错误 = "A";  ❌ 类型不匹配 

默认值差异

int 数量;         // 默认=0  
string 名字;      // 默认=null 
bool 是否测试;    // 默认=false 

💡 类型转换(跨柜子搬运)

自动转换(小柜→大柜)

int 小盒子 = 100;
double 大盒子 = 小盒子;  // ✅ 自动转成100.0 

强制转换(明确意图)

double 价格 = 9.9;
int 整数价 = (int)价格;  // 截断小数→9 

文本转数字

string 输入 = "123";
int 数字 = int.Parse(输入);  // 文字→数字 

🚀 一句话总结
数据类型就是给数据分门别类,让计算机知道:

能存什么(数字/文字/真假)
占多大空间
能做什么操作

试试这个例子:

int 座位数 = 36; 
double 上座率 = 0.85;
string 状态 = $"当前乘坐:{座位数 * 上座率}人";
Console.WriteLine(状态);  // 输出:当前乘坐:30.6人 

🌱 基元类型(Primitive Type)→ 编程语言的「原子」

(就像化学里的氢、氧等基本元素)

🧩 最简定义

基元类型是编译器直接支持的数据类型,无需额外定义,像乐高积木里的基础颗粒,用来组合出更复杂的结构。

📦 .NET 核心基元类型清单

类型 存储内容 例子 内存占用 现实比喻
bool 真/假 truefalse 1 bit 开关(开/关)
byte 0-255整数 2550xFE 1字节 像素颜色值
char 单个字符 'A''汉' 2字节 键盘按键
int 整数 -1002147483647 4字节 年龄、数量
double 小数 3.14-1.5e10 8字节 身高、体重
decimal 高精度小数 99.99m 16字节 货币金额
string 文本 "Hello" 变长 便签纸条
IntPtr 指针/句柄 内存地址 4/8字节 快递单号(定位数据位置)

🚀 为什么叫「基元」?

内置支持:像呼吸一样自然,无需using引用

int age = 25; // 直接使用,就像喝水一样基本 

性能最优:CPU直接处理,速度最快
不可再分:其他类型(如TimeSpan)都由它们组合而成

⚡ 特殊成员:String 的争议

虽然string属于基元类型,但它很特殊:

变长存储:像可伸缩的橡皮筋
不可变性:修改时实际是创建新字符串

string s = "A";
s += "B"; // 新建"AB",原"A"被丢弃 

🆚 基元 vs 非基元

特性 基元类型 非基元类型(如List
定义方式 语言内置 需通过类/结构体定义
性能 最优(直接内存操作) 需要额外的成员访问
示例 intchar DateTimeDictionary

💡 开发技巧

优先选择基元类型(除非有明确需求)

// 好:直接用int 
int count = 10; 

// 不好:过度封装 
class MyInt { public int Value { get; set; } }

注意数值范围

byte small = 300; // ❌ 编译错误(byte最大255)

科学计数法

double bigNum = 1.23e5; // = 123000 

🌰 现实类比

基元类型像面粉、水、糖 → 能直接做饼干
非基元类型像预制蛋糕 → 由面粉等基础材料制成

试试这段代码感受基元类型的简洁:

int 苹果 = 3;
double 单价 = 2.5;
Console.WriteLine($"总价:{苹果 * 单价}元"); 
// 输出:总价:7.5元 

🧩 C#基础数据类型 → 编程的「积木块」

(就像搭房子用的砖头、木板、玻璃等基本材料)

1. 最常用4大基础类型
类型 能存什么 例子 现实比喻
int 整数 3-100 完整苹果(不能切半)
double 小数 3.14-0.5 切开的苹果
bool 是/非 truefalse 开关(开/关)
string 文字 "你好""ABC" 便签纸

代码示例

int 年龄 = 25; 
double 价格 = 9.9;
bool 是否登录 = true;
string 名字 = "张三";

📊 数字类型细分(选合适的‘容器’)

类型 范围/精度 适用场景
byte 0~255 图片像素值
short ±3.2万 小计数器
int ±21亿 大多数整数场景
long ±9百万兆 天文数字/时间戳
float 7位小数 3D游戏坐标
double 15位小数 普通科学计算
decimal 28位小数 金融金额(钱)

示例

decimal 工资 = 9999.99m;  // 钱一定要用decimal!
float 体温 = 36.5f;       // 加f后缀 

✨ 特殊基础类型

类型 作用 例子
char 单个字符 'A''好'
DateTime 日期时间 DateTime.Now
object 万能类型(可装任何数据) object obj = 123;

注意

char 字母 = 'A';      // ✅ 单引号  
// char 错误 = "A";   ❌ 双引号是string 

⚠️ 新手常见坑

整数除法丢小数

double 错误 = 5 / 2;    // 得2(不是2.5)
double 正确 = 5 / 2.0;  // 得2.5 

decimal必须加m后缀

decimal 价格 = 9.9m;  // ✅  
// decimal 错误 = 9.9; ❌ 

string不可变

string s = "A";
s += "B";  // 实际新建"AB",原"A"被丢弃 

🔄 类型转换(跨积木兼容)

自动转换(小→大)

int 小 = 100;
double 大 = 小;  // 自动转成100.0 

强制转换(大→小)

int 小 = 100;
double 大 = 小;  // 自动转成100.0 

文本转数字

string 输入 = "123";
int 数字 = int.Parse(输入);  // 可能报错 
int 安全数字;
bool 成功 = int.TryParse(输入, out 安全数字);

💡 为什么重要?

节省内存byteint省3字节
避免错误:用decimal算钱不会丢精度
提升性能:CPU处理基元类型最快

🚀 一句话总结
C#基础类型就像不同尺寸的容器——选对盒子(类型)才能装好数据!

试试这个例子:

int 学生数 = 30;
double 平均分 = 85.5;
string 报告 = $"班级数据:{学生数}人,平均分{平均分}";
Console.WriteLine(报告); 

🧩 引用类型 vs 值类型 → 「快递盒」 vs 「实物」

1. 值类型(Value Type)→ 直接给「实物」

特点:数据直接存在变量里,像把苹果直接塞你手里
包含类型

基本类型(intdoubleboolchar
结构体(struct)、枚举(enum

内存分配:栈内存(快速存取)

代码示例

int a = 10;  // 直接把10放进a的盒子 
int b = a;   // 复制一个10给b(两个独立苹果)
b = 20;      // 只有b变成20,a仍是10 

现实比喻

值类型像发文件附件:对方修改附件不影响你的原文件

2. 引用类型(Reference Type)→ 给「快递单号」

特点:变量存储的是数据的内存地址,像给你快递柜的取件码
包含类型

类(class)、字符串(string)、数组(int[]
接口(interface)、委托(delegate

内存分配:堆内存(需GC回收)

代码示例

class 包裹 { public int 重量; }
 
包裹 我的包裹 = new 包裹 { 重量 = 5 }; // 在堆内存存包裹,我的包裹存的是地址 
包裹 你的包裹 = 我的包裹;               // 复制地址给你(同一份快递)
你的包裹.重量 = 10;                   // 修改的是同一份包裹! 
Console.WriteLine(我的包裹.重量);      // 输出10(因为指向同一个对象)

现实比喻

引用类型像共享在线文档:所有人编辑的是同一份文件

📊 核心区别对比表

特性 值类型 引用类型
存储内容 直接存数据 存内存地址
内存位置 栈(自动回收) 堆(GC回收)
赋值行为 复制整个数据 复制地址(共享对象)
默认值 0/false null
典型代表 intstruct classstring

🌰 经典场景示例

值类型场景(独立修改)
// 坐标结构体(值类型)
public struct 坐标 { public int X, Y; }
 
var 点A = new 坐标 { X = 1, Y = 2 };
var 点B = 点A;   // 复制值 
点B.X = 100;     // 不影响点A 

引用类型场景(共享修改)
// 学生类(引用类型)
public class 学生 { public string 姓名; }
 
var 小明 = new 学生 { 姓名 = "小明" };
var 小明的克隆 = 小明;   // 复制引用 
小明的克隆.姓名 = "克隆人"; 
 
Console.WriteLine(小明.姓名); // 输出"克隆人"(被改了!)

⚠️ 重要注意事项

字符串(string)的特殊性

虽然是引用类型,但修改时会创建新对象(表现得像值类型)

string s1 = "A";
string s2 = s1;  // 此时仍共享内存 
s2 = "B";        // 新建"B",s1仍是"A"

结构体(struct)的陷阱

尽量设计为不可变(避免混淆值/引用行为)

public readonly struct 不可变坐标 
{
    public int X { get; }
    public int Y { get; }
}

性能取舍

值类型:存取快,但大数据复制开销大
引用类型:适合大对象,但有GC压力

💡 如何选择?

用值类型当
✅ 小型数据(坐标、温度、金额)
✅ 需要频繁修改的临时变量
用引用类型当
✅ 复杂对象(学生、订单)
✅ 需要共享修改的数据

🚀 终极口诀
值类型是实物交接,引用类型是快递单号!

试试这段代码加深理解:

// 值类型 
int x = 10, y = x;
y = 20;
Console.WriteLine($"x={x}, y={y}"); // x=10, y=20 
 
// 引用类型 
var list1 = new List<int> { 1, 2, 3 };
var list2 = list1;
list2.Add(4);
Console.WriteLine(string.Join(",", list1)); // 1,2,3,4(共享修改)

🧩 进程 vs 线程 → 「工厂」 vs 「工人」

1. 进程(Process)→ 独立工厂

特点

拥有独立厂房(内存、文件等资源)
不同工厂隔离运作(一个工厂着火不影响其他)
启动慢(要建厂房、招工)

现实比喻

腾讯视频和微信就是两个进程 → 各自有独立资金和场地

2. 线程(Thread)→ 工厂工人

特点

共享同一厂房资源(共用进程的内存)
轻量级,创建/销毁快(临时工随叫随到)
工人间可能抢工具(需要锁机制协调)

现实比喻

微信进程内有:

主线程:处理界面点击
网络线程:下载文件
解码线程:播放视频

📊 核心对比表

特性 进程 线程
独立性 完全隔离 共享进程资源
开销 大(需要分配独立资源) 小(共享资源)
通信成本 高(需要IPC机制) 低(直接读写共享内存)
崩溃影响 不影响其他进程 可能导致整个进程崩溃
典型应用 不同软件(Chrome vs 微信) 同软件的多任务(下载+播放)

🌰 代码示例(C#多线程)

// 主线程 
Console.WriteLine("主线程开工!");
 
// 开新线程(新工人)
var worker = new Thread(() => {
    Console.WriteLine($"工人{Thread.CurrentThread.ManagedThreadId}在搬砖");
});
worker.Start();
 
// 输出可能:
// 主线程开工!
// 工人4在搬砖 

⚡ 技术要点

线程安全(防抢工具)

private static object _lock = new object();
lock (_lock) {
    // 临界区代码(一次只允许一个线程进入)
}

进程通信(IPC)方式

管道(Pipe)→ 像工厂间的传话筒
共享内存 → 两个工厂共用一块黑板

现代开发趋势

异步编程(async/await)比直接创建线程更高效
线程池:复用工人,避免频繁招工/解雇

💡 为什么需要多线程?

防止界面卡死

主线程负责UI,耗时操作(如下载)交给后台线程

利用多核CPU

4核CPU可同时跑4个线程(4个工人并行)

提升响应速度

浏览器用多线程同时下载图片/渲染页面

⚠️ 常见问题

死锁 → 两个工人互相等对方放下工具

// 线程A锁了资源1,请求资源2 
// 线程B锁了资源2,请求资源1 
// 结果:俩人永远等下去...

资源泄漏 → 工人离职没归还工具
线程过多 → 工人太多导致管理混乱

🚀 终极总结

进程是独立工厂 → 隔离性优先
线程是工厂工人 → 并发性优先

现实案例:
Chrome浏览器每个标签页是独立进程(防崩溃扩散),每个页面内用多线程处理渲染/网络请求。

🎯 变量 → 数据的“贴标签盒子”

(3秒极简版)
变量就是给数据贴个名字标签,方便随时找到和修改它!

📦 超通俗理解(现实类比)

想象你有一个收纳盒

贴标签:在盒子上写年龄(变量名)
放东西:盒子里放25这个数字(赋值)
换内容:把25改成26(修改变量值)
看内容:打开盒子看里面的数(读取变量)

代码示例

public 电饭煲() { }  // 自动生成 

🧩 变量的三个核心特征

有名字 → 盒子的标签(如age
能存值 → 盒子里放的东西(如25
可变/不变 → 是否允许换内容(普通变量 vs 常量

🌰 生活场景对比

变量操作 现实比喻 代码对应
定义变量 买个新盒子,贴上标签 int age;
赋值 往盒子里放东西 age = 25;
读取变量 打开盒子看内容 Console.WriteLine(age);
修改变量 替换盒子里的东西 age = 26;

⚠️ 新手常见误区

变量名 ≠ 值

public 电饭煲() { }  // 自动生成 

先贴标签,再放东西

public 电饭煲() { }  // 自动生成 

标签不能重名(同作用域)

public 电饭煲() { }  // 自动生成 

💡 为什么需要变量?

避免重复计算 → 存储结果反复使用

public 电饭煲() { }  // 自动生成 

动态修改值 → 如游戏积分实时更新

public 电饭煲() { }  // 自动生成 

代码可读性 → userAge比直接写25更易懂

📊 变量类型(不同尺寸的盒子)

类型 举例 适合存放的东西
int 10 整数(年龄/数量)
double 3.14 小数(价格/身高)
string "你好" 文本(名字/地址)
bool true 是否(是否登录/是否开启)

示例

public 电饭煲() { }  // 自动生成 

🚀 一句话总结

变量就是程序的“记忆便签”——贴个名字在数据上,随时找到、查看或修改它!

试试这个例子,感受变量的便利:

public 电饭煲() { }  // 自动生成 

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容