检查集合是否有物品的最佳做法是什么?
这是我的一个例子:
var terminalsToSync = TerminalAction.GetAllTerminals();
if(terminalsToSync.Any())
SyncTerminals(terminalsToSync);
else
GatewayLogAction.WriteLogInfo(Messages.NoTerminalsForSync);
Run Code Online (Sandbox Code Playgroud)
该GetAllTerminals()方法将执行一个存储过程,如果我们返回一个结果(Any()is true),SyncTerminals()将循环遍历这些元素; 从而再次枚举它并第二次执行存储过程.
避免这种情况的最佳方法是什么?
我想要一个可以在其他情况下使用的好解决方案; 可能没有把它转换成List.
提前致谢.
我可能会使用一个ToArray电话,然后检查Length; 无论如何你要列举所有的结果,为什么不早点呢?但是,既然你已经说过要避免早期实现可枚举......
我猜这SyncTerminals有一个foreach,在这种情况下你可以写这样的东西:
bool any = false;
foreach(var terminal in terminalsToSync)
{
if(!any)any = true;
//....
}
if(!any)
GatewayLogAction.WriteLogInfo(Messages.NoTerminalsForSync);
Run Code Online (Sandbox Code Playgroud)
好的,if在第一个循环之后有一个冗余,但我猜测额外的几个CPU周期的成本并不重要.
同样,你可以用旧的方式进行迭代并使用do...while循环GetEnumerator; 将第一次迭代从循环中取出; 这样就没有浪费的操作:
var enumerator = terminalsToSync.GetEnumerator();
if(enumerator.MoveNext())
{
do
{
//sync enumerator.Current
} while(enumerator.MoveNext())
}
else
GatewayLogAction.WriteLogInfo(Messages.NoTerminalsForSync);
Run Code Online (Sandbox Code Playgroud)
怎么样,它仍然推迟执行,但在执行后对其进行缓冲:
var terminalsToSync = TerminalAction.GetAllTerminals().Lazily();
Run Code Online (Sandbox Code Playgroud)
和:
public static class LazyEnumerable {
public static IEnumerable<T> Lazily<T>(this IEnumerable<T> source) {
if (source is LazyWrapper<T>) return source;
return new LazyWrapper<T>(source);
}
class LazyWrapper<T> : IEnumerable<T> {
private IEnumerable<T> source;
private bool executed;
public LazyWrapper(IEnumerable<T> source) {
if (source == null) throw new ArgumentNullException("source");
this.source = source;
}
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public IEnumerator<T> GetEnumerator() {
if (!executed) {
executed = true;
source = source.ToList();
}
return source.GetEnumerator();
}
}
}
Run Code Online (Sandbox Code Playgroud)