ArgumentNullException when deserializing a SortedList

D

Daniel Gackle

I'm getting a strange ArgumentNullException after deserializing a
SortedList. Haven't seen this discussed in the newsgroups, but it
looks like a bug - unless I missed something obvious? I've distilled
the problem into the following code. Can anybody reproduce/explain the
problem?

Thanks,
Daniel


using System;
using System.Collections;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace ConsoleApplication1
{
[Serializable]
class Class1 : ISerializable
{
private SortedList sortedListMember;
private DateTime sampleDate = new DateTime(1999, 9, 9);

public Class1()
{
sortedListMember = new SortedList();
sortedListMember[sampleDate] = 4.56;
}

void ISerializable.GetObjectData(SerializationInfo info,
StreamingContext context)
{
info.AddValue("sortedListMember", sortedListMember);
}

public Class1(SerializationInfo info, StreamingContext context)
{
readSortedList(info);
}

private void readSortedList(SerializationInfo info)
{
try
{
SortedList list = (SortedList)
info.GetValue("sortedListMember", typeof(SortedList));

// **** Executing this line causes an ArgumentNullException
****
object element = list[sampleDate];
}
catch (Exception e)
{
Console.WriteLine(e.GetType());
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
Console.ReadLine();
}
}

[STAThread]
static void Main(string[] args)
{
using (MemoryStream stream = new MemoryStream())
{
// serialize
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(stream, new Class1());

// go back to start before deserializing
stream.Position = 0;

// deserialize
bf = new BinaryFormatter();
bf.Deserialize(stream);
}
}
}
}
 
A

Ashish Kaila

My best guess is that sampleDate is null when you try the exception causing
statement.
Ashish
 
A

Alexander Shirshov

Daniel,

I tried your sample and it works. Are you sure there's a problem?

Alexander
 
D

Daniel Gackle

My best guess is that sampleDate is null when
you try the exception causing statement.

You obviously didn't read the code, let alone execute it. sampleDate
is clearly assigned. I took considerable care to distill this problem
down to code that precisely reproduces it. If I were passing a null
argument myself, a quick step through the debugger would have caught
it long ago.

Here's some additional info, in case one of the many helpful
contributors to this list gets a chance to look at the problem.

The exception message reports that the parameter name of the null
argument is "array". My code has no variable named "array". With the
help of the stack trace and Reflector, I've traced this back to the
field "keys" of the SortedList class being null after deserialization.
Now, every constructor of SortedList assigns a value to that
particular field. This suggests that there's a bug somewhere with
deserialization producing a SortedList that's in an invalid state.

Daniel
 
D

Daniel Gackle

I found the problem. The SortedList isn't populated until after
deserialization, so you can't attempt to access its contents inside
the serialization constructor. Instead, you have to implement
IDeserializationCallback and access the now populated list in the
OnDeserialization method.

Daniel
 
D

Daniel Gackle

Alexander,
I tried your sample and it works. Are you sure there's a problem?

As mentioned in my previous post, the main thing is that an object
graph that includes a SortedList (or a Hashtable) is not /guaranteed/
to be fully restored until after the serialization constructor exits.
So I guess it's unpredictable when it will work and when it will fail.
The solution is to implement IDeserializationCallback and wait for a
message.

Thanks for your reply,
Daniel

p.s. Even the IDeserializationCallback approach sometimes fails for
Hashtables! That is, you can deserialize an object that contains a
Hashtable, implement IDeserializationCallback, wait for the
OnDeserialization method to get called, and the hashtable is still
empty. This contradicts MS documentation which says that an object
graph is guaranteed to be fully deserialized when OnDeserialization is
called. Nevertheless, I'm seeing this problem, and so have others
(http://tinyurl.com/6cpau).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top