C# 传递Func委托时固定指定参数、剩余参数由方法内部赋值的实现方法
需求实现说明
这个需求完全可以实现,借助C#的闭包特性就可以完成,有两种改造方案可选:
方案1:最小改动(无需修改现有ExcelReader代码)
原有ExcelReader的委托签名要求传入接收3个参数的Func,你只需要在调用时用lambda表达式适配签名,捕获外部定义的dict、忽略方法内部传入的第三个参数即可:
private async Task OnFilesDropped(FileUploadModel upload) { var dict = new Dictionary<int, TreeItemModel>(); // 下划线代表忽略ExcelReader内部传入的第三个参数 OfficeHelper.ExcelExtension.ExcelReader(upload, (stringTable, row, _) => { // 直接使用外部捕获的dict作为参数传入 return ExcelToProjTree(stringTable, row, dict); }); }
这种方案不需要调整原有工具类代码,改造成本最低。
方案2:优化ExcelReader签名(调用更简洁)
如果你确认ExcelReader内部不需要自行维护dict实例,完全由调用方传入处理对象,可以直接修改ExcelReader的定义:
- 调整委托参数签名,移除不需要的第三个入参
- 可按需调整返回值(如果不需要返回内部创建的dict可改为void)
// 修改后的ExcelReader签名 public static void ExcelReader(FileUploadModel upload, Func<Dictionary<int, string>, Row, Action> func) { try { using (var doc = SpreadsheetDocument.Open(upload.Stream, false)) { var workbookPart = doc.WorkbookPart; var worksheetPart = workbookPart.WorksheetParts.First(); var sheetData = worksheetPart.Worksheet.Elements<SheetData>().First(); var stringTable = LoadSharedStringDictionarySax(workbookPart.SharedStringTablePart); foreach (var r in sheetData.Elements<Row>()) { // 调用委托时仅传入内部生成的两个参数 func(stringTable, r); } } upload.Stream.Close(); upload.UploadCompletion = 100; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); throw; } }
修改后调用代码更简洁:
private async Task OnFilesDropped(FileUploadModel upload) { var dict = new Dictionary<int, TreeItemModel>(); OfficeHelper.ExcelExtension.ExcelReader(upload, (stringTable, row) => ExcelToProjTree(stringTable, row, dict)); }
实现原理
C#的lambda表达式支持闭包特性,会自动捕获当前作用域的变量(示例中的dict),捕获的变量以引用方式传递,因此ExcelToProjTree中对dict的所有修改都会直接作用到你在调用处定义的实例,完全符合预期。
内容的提问来源于stack exchange,提问作者MarchalPT
相关产品推荐
相关产品推荐

