如何直接从函数返回ITaskItem[]数组,无需先存入List再转换?
直接生成ITaskItem[]替代List中转的方法
当前我的C#代码里,ReadItems()函数需要返回ITaskItem[]类型(微软要求MsBuild内联任务返回MsBuild Items时必须用这个类型)。现在的实现是先把从文件读取的符合正则规则的项存入List
现有代码
using System; using System.IO; using System.Text.RegularExpressions; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using System.Collections.Generic; namespace CS_Test { class Program { static ITaskItem[] ReadItems(string SrcPath) { List<ITaskItem> Items = new List<ITaskItem>(); string[] lines = File.ReadAllLines(SrcPath); foreach (string line in lines) { Match m = Regex.Match(line, @"(?^[^=\S\n]*(?<var>[^=\n\s]+)[^=\S\n]*=[^\S\n]*)(?<val>[^\n]*?)[^\S]*$"); if (m.Success) { ITaskItem it = new TaskItem(m.Groups["var"].Value); it.SetMetadata("val", m.Groups["val"].Value); Items.Add(it); } } return Items.ToArray(); } static void Main(string[] args) { ITaskItem[] Items = ReadItems(@"C:\vars.txt"); foreach (var it in Items ) { Console.WriteLine(it.ItemSpec + " == " + it.GetMetadata("val")); } } } }
C:\vars.txt 文件内容
aaa=111 bbb= ccc=333
解决方案
当然可以,用LINQ链式查询就能直接生成ITaskItem[],全程不需要List中转。修改后的ReadItems方法如下:
static ITaskItem[] ReadItems(string SrcPath) { var regex = new Regex(@"(?^[^=\S\n]*(?<var>[^=\n\s]+)[^=\S\n]*=[^\S\n]*)(?<val>[^\n]*?)[^\S]*$"); return File.ReadLines(SrcPath) .Select(line => regex.Match(line)) .Where(match => match.Success) .Select(match => { var taskItem = new TaskItem(match.Groups["var"].Value); taskItem.SetMetadata("val", match.Groups["val"].Value); return taskItem; }) .ToArray(); }
关键优化点
- 用
File.ReadLines替代File.ReadAllLines:前者是懒加载逐行读取,内存占用更低,适合大文件场景 - 提前创建Regex实例:避免在迭代过程中重复创建正则对象,提升性能
- LINQ链式调用直接完成读取行→匹配正则→过滤有效项→生成TaskItem的流程,最后通过
.ToArray()直接得到ITaskItem[],完全跳过List中转
内容的提问来源于stack exchange,提问作者Pavel Stepanek
相关产品推荐
相关产品推荐

