学习内容:
泛型用 <T> 表示,T 是类型参数 (Type Parameter),可以理解成类型占位符。一般是T开头或者直接T,只要有这个标志就是泛型,常见的List<int>这个就是泛型;类型参数是int
cs
class Test<T>//泛型类
{
}
public void TestRun<T>(T value)//泛型方法
{
}
一、作用(以及泛型类的声明)
有一个水果店,卖苹果买一个苹果用一个盒子包起来
cs
internal class Program
{
static async Task Main(string[] args)
{
Apple a = new Apple() { Color = "Red" };
Box b = new Box() { Cargo = a };
Console.WriteLine(b.Cargo.Color);
}
}
class Apple
{
public string Color { get; set; }
}
class Box
{
public Apple Cargo { get; set; }
}
如果这时候要买书的话就要重写建一个装书的box类
cs
class Book
{
}
class BookBox
{
public Book Cargo { get; set; }
}
这样会很麻烦这时候就可以用泛型,
cs
internal class Program
{
static async Task Main(string[] args)
{
Apple a = new Apple() { Color = "Red" };
Book bk = new Book() { Name = "xxx"};
Box<Apple> b = new Box<Apple>() { Cargo = a };
Box<Book> b1 = new Box<Book>() {Cargo = bk};
Console.WriteLine(b.Cargo.Color);
Console.WriteLine(b1.Cargo.Name);
}
}
class Apple
{
public string Color { get; set; }
}
class Book
{
public string Name { get; set; }
}
class Box<T> //使用了泛型
{
public T Cargo { get; set; }
}
////////////////
也可以
class Box<TCargo > //只要对的上
{
public TCargo Cargo { get; set; }
}
就可以知道泛型 = 通用的类型 + 通用的代码 它允许你写一套代码,适配任意类型(int、string、自定义类...),不用重复写多套逻辑。
二、泛型方法
在方法名字后面加<T> 这个方法就是泛型方法,下面例子就是交换两个相同类型的值;
cs
static void Swap<T>(ref T lhs, ref T rhs)//方法要两个T类型的参数
{
T temp; //声明一个T类型的参数temp
temp = lhs;
lhs = rhs;
rhs = temp;
}
比如
Swap(ref 1,ref 2);
这时候系统判断T是int类型,方法里的Temp就是int类型的
Swap(ref "s",ref "f");
这时候系统判断T是string类型,方法里的Temp就是string类型的
或者 用上一个例子的Apple类型也可以()
Apple a = new Apple() { Color = "Red" };
Apple a1 = new Apple() { Color = "Red1" };
Swap(ref a,ref a1);
这时候系统判断T是Apple类型,方法里的Temp就是Apple类型的,a的Color的值就是Read1了
三、泛型接口
有一个接口有个ID属性将来会有很多类型,所以使用了泛型;Student类来实现这个接口有两种形式;类也不管ID类型继续泛型下去;或者类明确id类型
cs
internal class Program
{
static async Task Main(string[] args)
{
Student student = new Student() { ID =1,Name = "xm"};
/////////////////////////////
Student<string> student1 = new Student<string>() { ID = "一",Name = "xh"};
Student<int> student2 = new Student<int>() { ID = 25, Name = "xh" };
}
}
interface IUnique<T>
{
public T ID { get; set; }
}
public class Student<T>:IUnique<T>//类也还是不知道id类型所以还是泛型
{
public string Name { get; set; }
public T ID { get; set; }
}
public class Student1 : IUnique<int>//类知道id类型是int
{
public string Name { get; set; }
public int ID { get; set; }
}
四、泛型约束
用于限制 T 能是什么类型,格式是where T : ...
4.1接口约束
cs
interface IAnimal
{
void Speak();
}
class Dog : IAnimal
{
public void Speak() => Console.WriteLine("汪汪");
}
// 约束 T 必须实现 IAnimal接口
void Test<T>(T animal) where T : IAnimal
{
animal.Speak(); // 有约束才能调用,否则编译器报错
}
常见约束
where T : struct // 必须是值类型(int、bool、DateTime 等)
where T : class // 必须是引用类型(类、接口、委托、数组)
where T : new() // 必须有无参构造函数
where T : 基类名 // 必须是该基类或其子类
where T : 接口名 // 必须实现该接口
where T : U // T 必须是 U 或 U 的子类
五、枚举(enum)
5.1.是什么?
枚举是一组命名的整型常量 ,专门用来表示固定不变的选项 / 状态,让代码更易读、更安全。常用结构如下
cs
// 定义枚举
enum 枚举名
{
常量1,
常量2,
常量3
}
常见例子:不定义的话从0开始,后面的加一
cs
// 定义:表示游戏角色状态
enum PlayerState
{
Idle, // 0(默认从0开始)
Run, // 1
Attack, // 2
Die // 3
}
// 使用
class Program
{
static void Main()
{
// 声明枚举变量
PlayerState state = PlayerState.Run;
// 枚举转整数
int stateNum = (int)state; // 结果:1
// 整数转枚举
PlayerState state2 = (PlayerState)2; // Attack
Console.WriteLine(state); // 输出:Run
}
}
5.2常见特性
5.2.1.可以自己定义数字
cs
enum Gender
{
Male = 1,
Female = 2,
Unknown = 99
}
而且如果只定义一个的话系统会自己加一
cs
enum Gender
{
Male ,
Female = 4,
Unknown
}
这种情况的话Male因为没有定义而且是第一个所以默认是0,Unknown =5因为定义了上一个所以默认加一得到5
5.2.2Flags 特性(允许组合多个值)
cs
[Flags] // 关键特性
enum Permission
{
None = 0,
Read = 1,
Write = 2,
Execute = 4
}
// 使用:同时拥有读和写权限
Permission p = Permission.Read | Permission.Write;
六、结构体(struct)
6.1. 是什么?
struct 是值类型 ,轻量、高效,适合封装少量简单数据(比如坐标、颜色、尺寸).类在内存上太大所以发明了结构体
6.2. 核心特点
- 值类型:赋值时会拷贝一份完整数据,不是引用
- 栈上分配(小型结构体),性能比类更好
- 不能继承,也不能被继承
- 可以有字段、方法、构造函数、属性
基本格式:
cs
struct 结构体名
{
// 字段/属性/方法
}
6.3 例子
cs
// 定义:坐标结构体
struct Point
{
// 字段
public int X;
public int Y;
// 构造函数
public Point(int x, int y)
{
X = x;
Y = y;
}
// 方法
public void Print()
{
Console.WriteLine($"X:{X}, Y:{Y}");
}
}
// 使用
class Program
{
static void Main()
{
// 创建结构体实例
Point p1 = new Point(10, 20);
p1.Print(); // X:10, Y:20
// 值类型特性:赋值是拷贝,互不影响
Point p2 = p1;
p2.X = 100;
Console.WriteLine(p1.X); // 10(没变)
}
}
6.4和类的对比
| 特性 | 结构体(struct) | 类(class) |
|---|---|---|
| 类型 | 值类型 | 引用类型 |
| 内存 | 栈(小型)/ 托管堆 | 托管堆 |
| 继承 | 不支持继承 | 支持继承 |
| 性能 | 高(轻量) | 相对较低 |
| 用途 | 小型数据(坐标、颜色) | 复杂对象(人、订单、车) |
学习时间:
26.03.31