目录
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实现了IComparable
Array.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)
{
// 可以安全地进行指针操作
}
}
学到了这里,咱俩真棒,记得按时吃饭(万圣夜快乐噢~)
【本篇结束,新的知识会不定时补充】
感谢你的阅读!如果内容有帮助,欢迎 点赞❤️ + 收藏⭐ + 关注 支持! 😊
C#泛型类型约束详解
1221

被折叠的 条评论
为什么被折叠?



