C#中使用LINQ构造对象时,如何避免重复调用方法赋值属性?
优化LINQ查询避免重复方法调用的几种方案
嘿,这个问题太常见了——重复调用同一个方法不仅写起来麻烦,要是getBeforeString内部做了比较耗时的操作,还会额外消耗性能。咱们来看看几种优雅的方式解决这个问题:
1. 使用LINQ的let子句(查询表达式风格)
这是最直接的方式,在查询里先一次性计算出getBeforeString的结果,后面直接复用就行:
var itemList = (from li in dictItem.valueElement let beforeText = StringParser.getBeforeString("(", li.InnerText) select new ItemWithNameAndUrl { Name = string.IsNullOrEmpty(beforeText) ? li.InnerText : beforeText, Url = li.Element("a").Attributes["href"].Value }).ToList();
2. 在Lambda块里先声明变量(方法链风格)
如果你更习惯用方法链形式的LINQ,也可以在lambda的块语法里先把结果存起来:
var itemList = dictItem.valueElement.Select(li => { var beforeText = StringParser.getBeforeString("(", li.InnerText); return new ItemWithNameAndUrl { Name = string.IsNullOrEmpty(beforeText) ? li.InnerText : beforeText, Url = li.Element("a").Attributes["href"].Value }; }).ToList();
3. 封装逻辑到局部函数/辅助方法
如果这个命名逻辑在多个地方用到,或者你想让LINQ查询更简洁,可以把逻辑抽出来成一个局部函数(或者单独的辅助方法):
// 局部函数,放在当前方法内部即可 string ResolveItemName(string innerText) { var beforeText = StringParser.getBeforeString("(", innerText); return string.IsNullOrEmpty(beforeText) ? innerText : beforeText; } // 然后查询就变得非常清爽 var itemList = dictItem.valueElement.Select(li => new ItemWithNameAndUrl { Name = ResolveItemName(li.InnerText), Url = li.Element("a").Attributes["href"].Value }).ToList();
4. 扩展方法(全局复用场景)
如果整个项目都需要类似的命名解析逻辑,还可以给StringParser加个扩展方法,把判断逻辑封装进去:
public static class StringParserExtensions { public static string GetBeforeOrOriginal(this StringParser parser, string separator, string text) { var beforeText = parser.getBeforeString(separator, text); return string.IsNullOrEmpty(beforeText) ? text : beforeText; } } // 调用的时候直接用扩展方法 var itemList = dictItem.valueElement.Select(li => new ItemWithNameAndUrl { Name = StringParser.GetBeforeOrOriginal("(", li.InnerText), Url = li.Element("a").Attributes["href"].Value }).ToList();
另外提个小建议:用string.IsNullOrEmpty()代替直接和string.Empty比较会更安全,因为它能同时处理null和空字符串的情况(万一getBeforeString返回null呢?)。
内容的提问来源于stack exchange,提问作者DVL
相关产品推荐
相关产品推荐

