一、泛型委托 核心概念
1. 普通委托弊端
普通自定义委托是固定类型,只能适配一种参数类型,复用性极差。
例如:CallBack(int a) 只能接收int类型,无法用于string、double等类型。
2. 泛型委托优势
泛型委托 = 通用万能委托
通过 <T> 延迟指定类型,一个委托适配所有数据类型,完美适配数组查询、筛选通用场景。
3. 自定义泛型委托语法(你的核心代码)
cs
// 泛型委托:任意类型T参数,返回bool(用于条件判断筛选)
public delegate bool CallBack<T>(T v);
作用:等价于系统内置的 Predicate<T>
二、手写通用Find方法(自定义泛型委托实现)
1. 方法功能
接收任意类型数组 + 条件委托 ,返回数组中第一个满足条件的元素。
2. 完整源码解析
cs
// 自定义泛型委托实现通用Find
public static T Find<T>(T[] arr, CallBack<T> c)
{
// 遍历数组所有元素
for (int i = 0; i < arr.Length; i++)
{
// 执行委托回调,判断当前元素是否满足条件
if (c(arr[i]))
{
return arr[i]; // 满足条件直接返回当前元素
}
}
return default(T); // 无匹配返回当前类型默认值
}
3. 调用演示
cs
// 整型数组筛选偶数
Console.WriteLine(Find<int>(new int[] { 1, 2, 3 }, v => v % 2 == 0)); //输出2
// 字符串数组筛选a开头
Console.WriteLine(Find<string>(new string[] { "aa", "bb", "cc" }, v => v.StartsWith("a"))); //输出aa
三、系统内置泛型委托 Predicate<T> 实现
Predicate<T>:系统自带泛型委托,固定签名 参数T、返回bool,专门用于筛选判断。
和你自定义的 CallBack<T>完全等价。
cs
// 系统内置Predicate实现通用Find
public static T Find1<T>(T[] arr, Predicate<T> c)
{
for (int i = 0; i < arr.Length; i++)
{
if (c(arr[i]))
{
return arr[i];
}
}
return default(T);
}
// 调用
Console.WriteLine(Find1<string>(new string[] { "aa", "bb", "cc" }, v => v.StartsWith("b"))); //输出bb
四、普通委托、Func委托 实现固定类型Find(对比学习)
1. Func<int,bool> 实现(内置委托)
cs
public static int MyFind1(int[] arr, Func<int, bool> f1)
{
for (int i = 0; i < arr.Length; i++)
{
if (f1(arr[i]))
{
return arr[i];
}
}
return -1;
}
2. 普通自定义委托实现(固定int类型)
cs
// 固定int类型委托,无法通用
public delegate bool CallBack(int a);
public static int MyFind2(int[] arr, CallBack f1)
{
for (int i = 0; i < arr.Length; i++)
{
if (f1(arr[i]))
{
return arr[i];
}
}
return -1;
}
3. 系统原生 Array.Find
cs
int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine(Array.Find(arr, v => v % 2 == 0)); //2
五、四种Find实现方式 终极对比
| 实现方式 | 是否通用 | 核心特点 |
|---|---|---|
| 普通自定义委托 | ❌ 不通用 | 固定类型,只能用int,复用性差 |
| Func 内置委托 | ❌ 不通用 | 需固定参数类型,适合单一类型业务 |
| 自定义泛型委托 | ✅ 全通用 | 自己定义委托,灵活度最高 |
| Predicate 泛型委托 | ✅ 全通用 | 系统内置,无需定义,筛选专用 |
六、default(T) 核心知识点
-
泛型中不知道T是什么类型,不能写固定默认值
-
default(T):自动返回当前泛型类型的默认值 -
值类型:int=0、bool=false
-
引用类型:string、类 = null
七、面试必考问答
1. 为什么要用泛型委托?
普通委托类型固定,只能适配单一类型;泛型委托通过T延迟绑定类型,支持任意类型的回调筛选,代码通用、复用性极强,是Array高阶方法的底层原理。
2. 自定义泛型委托和 Predicate<T> 的关系?
功能完全一致,都是【传入任意类型、返回bool】的筛选委托;Predicate是系统封装好的泛型委托,无需手动定义,开发中优先使用。
八、满分背诵口诀
-
普通委托类型死,只能单用不能通
-
泛型委托带个T,所有类型都兼容
-
Predicate专判断,布尔返回是本能
-
自定义委托最灵活,系统委托最省心
-
default(T)万能默认,泛型兜底不报错