cad.net 委托
定义
委托就是函数指针,就是回调函数.
它用了一个函数指针链构成多播,
这样才可以+=和-=,是事件实现底层,
不过事件要event关键字才可以反射到.
视频参考
它形成了一种夹芯饼干式的编程方法,
饼干的两端是固定的,把芯的内容抛出去给调用的人.
为什么这么做呢?
我认为最重要的是写SDK的,和调用者不是同一个人,
但是写SDK的人想调用者写的函数插在这个函数的中间.
无返回值的Action
/// <summary>
/// 事务委托
/// </summary>
/// <param name="db">数据库对象</param>
/// <param name="ac">委托,输出事务</param>
/// <param name="commit">是否提交,默认提交</param>
public static void Action(this Database db, Action<Transaction> ac, bool commit = true) {
var tr = db.TransactionManager.StartTransaction();
try {
ac.Invoke(tr); // 事务就被传出去了
} catch (Exception e) {
Debugger.Break();
} finally {
if (tr != null && !tr.IsDisposed) {
if (commit && tr.TransactionManager.NumberOfActiveTransactions > 0)
tr.Commit();
tr.Dispose();
}
}
}
调用:
db.Action(tr => { ... });
但是这样写函数有几个缺点,
调用的时候需要套入函数体内,这样比较丑.
为什么说丑?
因为增加了一层大括号,圈复杂度变高,
很多时候委托内还有委托,嵌套好几层....
这个事务委托改用新版语法的using,你就发现这样更美.
void Test() {
using var tr = db.TransactionManager.StartTransaction();
...
tr.Commit();
}
关于事务,我们已经从 事务委托 改为 事务栈
有返回值的Func
// 功能是搜索第一个满足条件,然后中断搜索.
// bool就是返回值类型
public int MyFirst(List<int> list, Func<int, bool> func) {
foreach(var item in list) {
var flag = func(item);
if (flag) return item;
}
// 没有成功选中,会返回默认值.
return default;
}
// 调用
public static void Main() {
var list = new List<int>() { 1,2,3,4,5,6,7,8,9 };
var result = MyFirst(list, a => a == 3);
// 没有成功选中,会返回默认值.
if (result == default)
return;
}
我上面实现了一个int版本,
而微软在Linq实现是泛型版本,更通用:
// 泛型版本
var result = list.FirstOrDefault(a => a==3);
// 它速度快,内部是for而不是foreach,
// 它是List专用,Array/HashSet/Dictionary就用不了.
var result = list.Find(a => a==3);
// 下面这个,它找不到会报错,最好别用
var result = list.First(a => a==3);
技巧
实际上我们不喜欢Func,但是我们需要这个中断标记.
那么怎么办呢?
1, 结构体是值类型会被拷贝值,外部改了内部也没变,除非ref.
2, 类是引用类型,所以传输出去之后内部和外部都是同一个.
那么要是Action的其中一个参数是类就好了.
public int MyFirst(List<int> list, Action<int, LoopState> func) {
LoopState state = new();
foreach(var item in list) {
func(item, state);
if (!state.IsRun) return item;
}
// 没有成功选中,会返回默认值.
return default;
}
// 调用
public static void Main() {
var list = new List<int>() { 1,2,3,4,5,6,7,8,9 };
var result = MyFirst(list, (a, state) => {
if (a == 3)
state.Break();
});
// 没有成功选中,会返回默认值.
if (result == default)
return;
}
(完)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)