Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我在这里重复这个枚举两次吗?_C#_Algorithm_Optimization - Fatal编程技术网

C# 我在这里重复这个枚举两次吗?

C# 我在这里重复这个枚举两次吗?,c#,algorithm,optimization,C#,Algorithm,Optimization,考虑以下代码块: using (FileStream fs = new FileStream(@"C:\bad_records.txt", FileMode.Create, FileAccess.Write)) { var badEnumerable = _cache.Where(kvp => !kvp.Value.Item1)

考虑以下代码块:

using (FileStream fs = new FileStream(@"C:\bad_records.txt", 
                                      FileMode.Create, 
                                      FileAccess.Write))
{
    var badEnumerable = _cache.Where(kvp => !kvp.Value.Item1);

    fs.WriteLine(string.Format("BAD  RECORDS ({0})", badEnumerable.Count()));
    fs.WriteLine("==========");

    foreach (var item in badEnumerable)
    {
        fs.WriteLine(string.Format("{0}: {1}", item.Key, item.Value.Item2));
    }
}
其中
\u cache
的定义如下:

static Dictionary<string, Tuple<bool, string, string>> _cache;
静态字典\u缓存;

我是否迭代此可枚举项两次?一次使用
Count()
和一次使用
foreach

是的,您迭代此可枚举项两次

测试这一点的简单方法是使用以下帮助器方法:

private static int count = 0;
public static IEnumerable<T> CountIterations<T>(IEnumerable<T> sequence)
{
    count++;
    //or some other debug type logging
    Console.WriteLine("Iterated {0} times.", count);
    foreach(var item in sequence)
        yield return item;
}
private static int count=0;
公共静态IEnumerable CountIterations(IEnumerable序列)
{
计数++;
//或者其他一些调试类型的日志记录
WriteLine(“迭代了{0}次。”,count);
foreach(序列中的var项目)
收益回报项目;
}

是,为避免重复两次,请使用
列表
您可以在初始迭代后打印计数。 另一种解决方案是保存循环中写入的文本,并在打印计数后打印

编辑更正:

using (FileStream fs = new FileStream(@"C:\bad_records.txt", FileMode.Create, FileAccess.Write))
{
    var badEnumerable = _cache.Where(kvp => !kvp.Value.Item1);

    int count = 0;
    foreach (var item in badEnumerable)
    {
        count++;
        Console.WriteLine(string.Format("{0}: {1}", item.Key, item.Value.Item2));
    }

    Console.WriteLine("==========");
    Console.WriteLine(string.Format("BAD  RECORDS ({0})", count));
}

您可以使用字典
\u缓存
作为
KeyValuePair
IEnumerable
其中方法已延迟执行。
因此,您将它枚举两次:在
Count
和在
foreach

您可以将其更改为:
var badEnumerable=_cache.Where(kvp=>!kvp.Value.Item1.ToArray()
fs.WriteLine(string.Format(“坏记录({0})”,badEnumerable.Length)

是的,
.Count()
foreach
都会导致
\u缓存
被枚举两次,并根据
中的谓词进行验证,其中
原因

至于这是否是一个问题,取决于许多因素:

  • \u cache
    中的所有值是否都已存在于内存中,或者它正在查询底层源(如数据库)
  • 查询的集合中有多少项,比较的成本是多少
  • 可以安全地多次枚举源
  • 例如,如果
    \u cache
    中的值已经在内存中,并且谓词是简单的布尔属性比较,则枚举缓存两次可能更有效,不会增加额外的内存开销,而添加
    .ToList()
    仍将导致两次枚举(一个
    \u缓存和一个列表)但是谓词检查只会发生一次(在
    .ToList()
    调用中),并且
    foreach
    将有更少的对象要枚举,但您将增加额外列表的额外内存开销


    如果缓存来自数据库,则在
    .Where()
    之后添加
    .ToList()
    的内存开销几乎肯定比对数据库执行两次单独查询要好。

    简短的回答是肯定的

    根据
    badEnumerable
    的基本类型,它可能会被枚举两次。这是由于所谓的“.延迟执行意味着您的LINQ查询在foreach或For Each循环(MSDN)中对查询变量进行迭代之前”不会实际执行。您的
    foreach
    语句显然是对变量的迭代,并且
    Enumerable.Count()
    也执行迭代(在本例中)

    但在某些情况下,这不会导致两次迭代。在这种情况下,调用
    .Count()
    实际上引用了底层的
    .Count
    属性,并且不枚举它


    因为
    badEnumerable
    是一个
    Dictionary
    ,也因为调用
    Enumerable.Where()
    返回一个通用的
    IEnumerable
    (一个不是
    ICollection
    ),您的特定案例不会遇到这种情况,将重复两次。

    是的,何处延迟了执行。为了得到明确的答案,我们需要知道缓存是什么类型的…@AakashM不知道。我们知道它被重复了两次。我们不知道这是否是一件非常糟糕的事情;重复它可能完全可以两次,或者这可能非常可怕,但我们可以100%肯定他重复了两次。我相信你自己的辩证能力可以理解这一点——这似乎是一个出于疑问的问题。@servy从提供的
    \u cache
    示例中可以是任何东西,比如说,包括一个带有扩展方法的类,它取代了中的扩展方法de>可枚举的
    ,例如提供一个
    计数()
    方法,该方法实际上没有枚举…没有任何解释,这不是一个真正有价值的答案。它似乎太简单了P@ashes999好的,解释实际上是在问题本身,
    Count
    foreach
    每次迭代
    IEnumerable
    。虽然我添加了一个sim卡,但没有太多要说的有多种方法可以更容易地观察到它。@Servy,这正是我所期望的。这些列表非常小(例如,最多15000个),因此这可能不是一个真正的目标问题,但事实上你已经完全证实了我的怀疑。非常感谢你的朋友!这个方法应该取代对
    .Count()的调用吗
    ?如果是这样,那么它只是因为
    badEnumerable
    的类型才正确,并且这不能用于测试“does
    .Count()
    枚举两次?”的一般情况,如果
    badEnumerable
    实现了
    ICollection
    ,那么
    .Count()
    不会产生两次迭代,但您的代码会。如果您投反对票,请至少留下一个简短的解释,说明为什么这个答案不正确。