如何正确检查IEnumerable的现有结果

Fed*_*jdu 5 c# linq

检查集合是否有物品的最佳做法是什么?

这是我的一个例子:

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.

提前致谢.

And*_*tan 5

我可能会使用一个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)


Mar*_*ell 3

怎么样,它仍然推迟执行,但在执行后对其进行缓冲:

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)

  • 不过,这与调用 ToList() 并没有什么不同! (3认同)