C#,WinForms:ListBox.Items.Add生成一个OutOfMemoryException,为什么?

首先,我找到了exception的解决方案。 我更好奇为什么它会产生特定的例外。

在我的场景中,我正在向ListBox中添加一个POCO ,如下所示:

myListBox.Items.Add(myPOCO); 

这产生了一个OutOfMemoryException 。 问题是,关闭POCO的ToString返回null 。 我添加了一个string.IsNullOrEmpty检查以在null时返回“安全”值并且exception消失。

为什么这会产生OutOfMemoryException而不是其他东西(比如说NullReferenceException )?

编辑 :项目在for循环中添加。

完整的调用堆栈(删除了公司特定的引用)如下。 有一点需要注意 – 调用它时列表框为空。

 System.OutOfMemoryException was unhandled Message="List box contains too many items." Source="System.Windows.Forms" StackTrace: at System.Windows.Forms.ListBox.NativeAdd(Object item) at System.Windows.Forms.ListBox.ObjectCollection.AddInternal(Object item) at System.Windows.Forms.ListBox.ObjectCollection.Add(Object item) at 
_Load(Object sender, EventArgs e) in \.cs:line 52 at System.Windows.Forms.Form.OnLoad(EventArgs e) at System.Windows.Forms.Form.OnCreateControl() at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible) at System.Windows.Forms.Control.CreateControl() at System.Windows.Forms.Control.WmShowWindow(Message& m) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ScrollableControl.WndProc(Message& m) at System.Windows.Forms.ContainerControl.WndProc(Message& m) at System.Windows.Forms.Form.WmShowWindow(Message& m) at System.Windows.Forms.Form.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) at System.Windows.Forms.SafeNativeMethods.ShowWindow(HandleRef hWnd, Int32 nCmdShow) at System.Windows.Forms.Control.SetVisibleCore(Boolean value) at System.Windows.Forms.Form.SetVisibleCore(Boolean value) at System.Windows.Forms.Control.set_Visible(Boolean value) at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.RunDialog(Form form) at System.Windows.Forms.Form.ShowDialog(IWin32Window owner) at System.Windows.Forms.Form.ShowDialog() at .Program.Main() in \Program.cs:line 25 at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args) at System.Runtime.Hosting.ManifestRunner.Run(Boolean checkAptModel) at System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly() at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext, String[] activationCustomData) at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext) at System.Activator.CreateInstance(ActivationContext activationContext) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()

这是因为System.Windows.Forms.ListBox.NativeAdd方法的实现方式:

 private int NativeAdd(object item) { int num = (int) base.SendMessage(0x180, 0, base.GetItemText(item)); switch (num) { case -2: throw new OutOfMemoryException(); case -1: throw new OutOfMemoryException(SR.GetString("ListBoxItemOverflow")); } return num; } 

GetItemText方法在返回null的对象上使用ToString() ,因此使用null参数发送消息,该参数又返回无效指针,并输入引发exception的第二种情况。

当底层LB_ADDSTRING Windows API调用失败时,WinForms始终返回OutOfMemoryException 。 .NET Framework参考源中的注释解释了原因:

 // On some platforms (eg Win98), the ListBox control // appears to return LB_ERR if there are a large number (>32000) // of items. It doesn't appear to set error codes appropriately, // so we'll have to assume that LB_ERR corresponds to item // overflow. // throw new OutOfMemoryException(SR.GetString(SR.ListBoxItemOverflow));