C#知识学习-019(泛型类型约束关键字)
目录
1.new约束
1.1 概念
1.2 通俗解释
1.3 举例
2.where泛型类型约束
2.1 基本语法
2.2 常用的约束类型
2.2.1 接口约束(必须实现某个接口)
2.2.2 基类约束(必须是某个类的子类)
2.2.3 引用类型约束 (class)
2.2.4 值类型约束 (struct)
2.2.5 无参数构造函数约束 (new())
2.2.6 非托管类型约束 (unmanaged)
1.new约束
1.1 概念
new约束就像给泛型类型参数设置了一个规则:"这个类型 T 必须能够用 new T()的方式创建对象"
-
什么是泛型约束?泛型约束就是给泛型类型参数设置限制条件,告诉编译器这个类型参数必须满足什么要求。
-
什么是泛型?泛型允许我们编写可以处理不同数据类型的类或方法,而无需为每个类型重复编写代码。
-
什么是约束?约束是限制泛型类型参数可以为什么类型的一种方式。例如,我们可以要求类型参数必须实现某个接口或继承某个类。
-
new约束:它要求类型参数必须有一个公共的无参数构造函数。这样我们就可以在泛型类中创建该类型的实例。若要使用new约束,类型不能是抽象的。
1.2 通俗解释
你开了一家玩具工厂,但这个工厂很特别:
// 你的玩具工厂规定:只能生产那些"一按按钮就能出来"的玩具
class 玩具工厂<T> where T : new()
{public T 生产玩具(){return new T(); // 就像按一下按钮,玩具就出来了}
}
符合要求的玩具:
-
洋娃娃(拆开包装就能玩)
-
球类(拿出来就能玩)
class 洋娃娃 { } // 可以直接 new 洋娃娃()
class 球类 { } // 可以直接 new 球类()
不符合要求的玩具:
-
需要组装的模型飞机(需要先拼装)
-
抽象的概念(比如"快乐",无法具体制造)
class 模型飞机
{ public 模型飞机(string 说明书) { } // 需要说明书才能组装
}abstract class 快乐 { } // "快乐"是抽象概念,无法制造
1.3 举例
// 使用示例
Factory<Product> factory = new Factory<Product>();
Product product = factory.CreateInstance();
Console.WriteLine(product.Name);// 简单的类
public class Product
{public string Name { get; set; } = "Default";// 这就是构造函数 - 方法名与类名相同,没有返回类型// 构造函数不需要传入任何值,所以是无参数构造函数public Product(){Console.WriteLine("Product created");}
}// 使用 new() 约束的泛型类
public class Factory<T> where T : new()
{public T CreateInstance(){return new T(); // 这里可以安全使用 new T()}
}
补充:
- "无参数"指的是构造函数不需要传入任何值
// 无参数构造函数 - 创建时不需要传值
public class Product
{public Product() // 括号里是空的,没有参数{// 创建对象时:Product p1 = new Product();}
}// 有参数构造函数 - 创建时需要传值
public class Product
{public Product(string name) // 括号里有参数{// 创建对象时:Product p2 = new Product("iPhone"); }
}
-
定义泛型工厂类
-
Factory<T>是一个泛型类,其中的T可以是任何类型 -
where T : new()是约束,意思是:"T 必须能用 new T() 来创建" -
因为有了这个约束,在
CreateInstance()方法中写new T()是安全的
-
-
执行流程
-
创建工厂:
Factory<Product> factory = new Factory<Product>();-
这里把
Product类型传给Factory<T>的T -
编译器检查
Product是否符合new()约束(确实符合,因为 Product 有无参数构造函数)
-
-
创建产品:
Product product = factory.CreateInstance();-
调用
factory.CreateInstance(),方法内部执行return new T();此时T是Product,所以相当于new Product() -
执行 Product 的构造函数,输出 "Product created",返回一个 Product 对象
-
-
补充:
当你有多个约束时,new()必须放在最后面。
举例:
public class ItemFactory2<T>where T : IComparable, new() // new() 在最后
{ }
为什么有这个规则?
这就像写地址时的顺序:国家 → 城市 → 街道 → 门牌号
在约束中,顺序是:基类/接口 → 构造函数约束
补充:
IComparable是一个接口,它让对象能够比较大小。
对于具体类型,可以直接比较:
int a = 5, b = 3;
bool result = a > b;
泛型类型 T 在编译时是未知的:
public class SortingFactory<T> where T : new()
{public void SortItems(T[] items){// 这里不能直接比较,因为不知道T有没有比较能力// if (items[0] > items[1]) // 编译错误!// Array.Sort(items); // 编译错误!}
}
为了让编译器知道 T可以比较:
public class SortingFactory<T> where T : IComparable, new()
{public void SortItems(T[] items){// 现在可以了,因为编译器知道T实现了IComparableArray.Sort(items); // 可以排序}public T GetMax(T a, T b){// 可以比较大小return a.CompareTo(b) > 0 ? a : b;}
}
2.where泛型类型约束
2.1 基本语法
public class 类名<T> where T : 约束条件
{// 类内容
}
2.2 常用的约束类型
2.2.1 接口约束(必须实现某个接口)
// T 必须实现 IComparable<T> 接口
public class Sorter<T> where T : IComparable<T>
{public void Sort(T[] items){// 这里可以调用 items[i].CompareTo() 方法// 因为 T 肯定有 CompareTo 方法}
}
2.2.2 基类约束(必须是某个类的子类)
// T 必须是 Animal 或其子类
public class Zoo<T> where T : Animal
{public void MakeSound(T animal){animal.Eat(); // 可以调用 Animal 的方法}
}
2.2.3 引用类型约束 (class)
// T 必须是引用类型(类、接口、委托等)
public class ReferenceContainer<T> where T : class
{public T Item { get; set; }
}
2.2.4 值类型约束 (struct)
// T 必须是值类型(int, double, struct 等)
public class ValueContainer<T> where T : struct
{public T Value { get; set; }
}
2.2.5 无参数构造函数约束 (new())
// T 必须有无参数的构造函数
public class Factory<T> where T : new()
{public T CreateInstance(){return new T(); // 可以创建实例}
}
2.2.6 非托管类型约束 (unmanaged)
// T 必须是非托管类型(基本数值类型、枚举、指针等)
public unsafe class UnmanagedProcessor<T> where T : unmanaged
{public void Process(T* pointer){// 可以安全地进行指针操作}
}
学到了这里,咱俩真棒,记得按时吃饭(万圣夜快乐噢~)
【本篇结束,新的知识会不定时补充】
感谢你的阅读!如果内容有帮助,欢迎 点赞❤️ + 收藏⭐ + 关注 支持! 😊
