【问题标题】:Adding items to a List<T> / defensive programming将项目添加到 List<T> / 防御性编程
【发布时间】:2009-04-23 09:45:53
【问题描述】:

在添加到 C# 列表时明确检查/处理您没有达到 2^31 - 1 (?) 的最大条目数是疯狂的,是真是假?

(假设这是一个平均列表大小小于 100 的应用。)

【问题讨论】:

    标签: c# defensive-programming


    【解决方案1】:

    1.内存限制

    嗯,没有任何属性的 System.Object 的大小是 8 字节(2x32 位指针),或 64 位系统中的 16 字节。 [编辑:]其实我刚签入WinDbg,大小在x86(32位)上是12bytes。

    因此,在 32 位系统中,您需要 24Gb 内存(在 32 位系统上无法拥有)。

    2。程序设计

    我坚信如此大的列表不应该保存在内存中,而应该保存在其他一些存储介质中。但在这种情况下,您将始终可以选择创建一个包装 List 的 cached 类,该类将在后台处理实际存储。因此,在添加之前测试大小是错误的测试位置,如果有一天您发现有必要,您的 List 实现应该自己做。

    3.为了安全起见

    为什么不在每个方法中添加一个重入计数器来防止堆栈溢出? :)

    所以,是的,为此进行测试太疯狂了。 :)

    【讨论】:

      【解决方案2】:

      似乎过分了。根据列表中对象的大小,您不会先达到机器的内存限制吗? (我假设这个检查是由 List 类的用户执行的,在实现中没有任何检查?)

      也许同事们都在提前考虑,这让人放心? (讽刺!)

      【讨论】:

        【解决方案3】:

        看起来是这样,我可能不会包括支票,但我对此感到矛盾。程序员曾经认为 2 位数字足以在日期字段中表示年份,理由是这对于他们的代码的预期寿命来说很好,但是我们发现这个假设是不正确的。

        查看风险,查看努力并做出判断(也称为有根据的猜测!:-))。我不会说这有什么硬性规定。

        【讨论】:

          【解决方案4】:

          正如上面的答案一样,我怀疑会出现更多问题而不是担心。但是,如果你有时间和意愿,你可以打磨代码直到它发光!

          【讨论】:

            【解决方案5】:

            是的

            (好吧,你问的是真还是假..)

            【讨论】:

              【解决方案6】:

              刚刚试过这段代码:

              List<int> list = new List<int>();
              while (true) list.Add(1);
              

              我遇到了 System.OutOfMemoryException。那么你会怎么做来检查/处理这个?

              【讨论】:

              • 你捕获了 OutOfMemoryException。通常可以处理 OOM,并在一分钟内重试操作。例如。两个单独的线程要求大量内存,只有 1 个得到它。稍后尝试第二个。如果您的应用在内存中执行 PDF 或图像处理,有时会发生这种情况。
              【解决方案7】:

              如果您继续向列表中添加项目,那么在您达到该限制之前很久就会耗尽内存。我所说的“长”实际上是指“比你想象的要快得多”。

              请参阅大对象堆 (LOB) 上的 this discussion。一旦你达到了大约 21500 个元素(在 64 位系统上只有一半)(假设你正在存储对象引用),你的列表将开始成为一个大对象。由于 LOB 的压缩方式与普通 .NET 堆不同,因此您最终会将其碎片化到无法分配足够大的连续内存区域的程度。

              因此您根本不必检查该限制,这不是真正的限制。

              【讨论】:

                【解决方案8】:

                是的,这太疯狂了。

                考虑当您开始达到这些数字时,其余代码会发生什么。如果列表中有数百万个项目,该应用程序是否可用?

                如果应用程序甚至有可能达到这样的数据量,也许您应该采取措施来防止列表变得那么大。也许您甚至不应该一次将所有数据保存在内存中。我真的无法想象任何代码都可以实际使用这么多数据的场景。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-10-10
                  • 2010-09-28
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多