我正在查看以下代码
public IEnumerable<RoleRecord> GetRoles() {
var roles = _roleRepository.Table.Select(role => role);
return roles.ToList();
}
Table
是_IQueryable<RoleRecord> Table { get; }
有没有更好的方法来写这个?
有效地投射到自己身上——所以这里Select(role => role)
基本上什么都不做。
return _roleRepository.Table.ToList();
...将达到相同的效果,或者:
return _roleRepository.Table;
如果您很高兴返回可枚举而不是已解决的列表。
这是在猜测Table
是否有IEnumerable<T>
资格获得Select()
or ToList()
。
将ToList
完全迭代Table
可枚举,但返回为IEnumerable<T>
. 其消费者将迭代列表,这可能比迭代Table
.
更新:IEnumerable<T>
在与@servy 聊天后,返回 an (在您的情况下为 from Select(role => role)
)和返回 a之间的一个重要区别List<T>
是,使用 a List<T>
,调用者可以将您的IEnumerable<T>
背部转换为 aList<T>
并对其进行变异:
IEnumerable<RoleRecord> results = GetRoles();
var asList = (List<RoleRecord>)results;
asList.Add(new RoleRecord());
asList.RemoveAt(0);
但是请注意,自投影不是这里的决定因素,这是您使用迭代器块作为IEnumerable<T>
实现而不是List<T>
.
也就是说,这种特殊的行为差异在您的情况下不会很明显,因为您调用ToList()
了 ,因此原始答案中的代码代表 - 它是等效的(并且在技术上稍快)。
如果没有任何过滤条件,则无需调用 Select。
就像是:
public IEnumerable<RoleRecord> GetRoles() {
return _roleRepository.Table.ToList();
}
会更简单吗?调用 .ToList() 显然会使集合水化,但我认为这就是你想要的。
这应该简化为:
public IEnumerable<RoleRecord> GetRoles() {
return _roleRepository.Table.ToList();
}
基本上,a => a
只是一个“身份”的投影,也就是a
自己。在这种情况下,它真的不买任何东西。
在某些情况下,当您不想执行某项操作时,它有时可用作占位符。但是,在这种情况下,没有必要,因为最终结果只是对ToList()
原始序列执行 a ,而无需Select()
.
当然,这是假设原始方法中的两行之间没有其他任何事情发生。
LINQ 的Select(a => a)
作用是什么?
它将序列的每个元素投影到一个新形式中,该形式仅包含您指定的元素(您的“a”)。
我相信你可以写:
public IEnumerable<RoleRecord> GetRoles() {
return _roleRepository.Table.ToList();
}
如果没有,那你可以试试
return (from r in _roleRepository.Table select r).ToList();
Select 方法返回一个“投影”——对源可枚举的每个单独元素的修改。在这种情况下,它将元素投影到自身,因此它是多余的。
如果我不得不猜测意图,我会说选择被包括在内,并且查询没有与其“ToList()”终止符内联(强制对 Linq 链的评估以产生所有元素),因此它可以更容易调试以准确查看查询生成了哪些元素。或者,这个查询可能最初是由精通 SQL 的人编写的,他认为所有 LINQ 查询都应该包含 SQL SELECT 查询的部分。
不管怎样,除了去掉 Select 之外,这个查询还可以内联在返回中:
public IEnumerable<RoleRecord> GetRoles() {
return _roleRepository.Table.ToList();
}