C#, WinForms: ListBox.Items.Add generates an OutOfMemoryException, why?
c#, winforms
Solution
This is because of the way `System.Windows.Forms.ListBox.NativeAdd` method is implemented:
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;
}
The GetItemText method uses `ToString()` on the object which returns `null` and so a message is sent with `null` parameter, which in turn returns an invalid pointer and you enter the second case which throws the exception.
Problem
First off, I found the solution to the exception. I'm more curious why it generated the specific exception it did. In my scenario I'm adding a POCO to a ListBox like so: ``` myListBox.Items.Add(myPOCO); ``` This was generating an `OutOfMemoryException`. The problem was that `ToString` off the POCO was returning `null`. I added a `string.IsNullOrEmpty` check to return a "safe" value when null and the exception went away. Why does this generate an `OutOfMemoryException` and not something else (say a `NullReferenceException`)? EDIT: Items are added in a for loop. Full call stack (company-specific references removed) is below. One thing to note -- the list box is empty when this is called. ``` 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 <FORM>_Load(Object sender, EventArgs e) in <PATH>\<FORM>.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 <APP>.Program.Main() in <PATH>\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() ```