Hi guys,
after long time of abstinence I found an interesting issue to talk about. In our web project we are putting some context informations into the view state, like 1000 other web applications too I think. We developed a special class that holds the values – it called “Context”.
This context class holds some NonSerialized Members like a local cache designed as a hashtable. The problem ist, that after de-serializing the context class the local cache is not initialized although we initialized it within the constructor.
That’s strange – and I have to confess that I really don’t know why it happens.
Here’s a small the example of the context that fails:
/// <summary>
/// Context class
/// </summary>
[Serializable]
public class ContextThatFails
{
private string serializedValue;
[NonSerialized]
private Hashtable localCache;
/// <summary>
/// Initializes a new instance of the <see cref="ContextThatFails"/> class.
/// </summary>
public ContextThatFails()
{
/*
* The constructor won't be used when de-serializing the object
*/
localCache = new Hashtable();
}
/// <summary>
/// Gets the local cache.
/// </summary>
/// <value>The local cache.</value>
public Hashtable LocalCache
{
get { return localCache; }
}
/// <summary>
/// Gets or sets the serialized value.
/// </summary>
/// <value>The serialized value.</value>
public string SerializedValue
{
get { return serializedValue; }
set { serializedValue = value; }
}
}
When trying to access the hashtable after de-serializing the context the compiler will throw a NullReferenceException.
We solved this problem by verifying the value when accessing the property.
The solution looks like that:
/// <summary>
/// Context class
/// </summary>
[Serializable]
public class ContextThatSucceeds
{
private string serializedValue;
[NonSerialized]
private Hashtable localCache;
/// <summary>
/// Gets the local cache.
/// </summary>
/// <value>The local cache.</value>
public Hashtable LocalCache
{
get
{
/*
* We have to initialize the hashtable on access.
*/
if (localCache == null)
localCache = new Hashtable();
return localCache;
}
}
/// <summary>
/// Gets or sets the serialized value.
/// </summary>
/// <value>The serialized value.</value>
public string SerializedValue
{
get { return serializedValue; }
set { serializedValue = value; }
}
}
The complete source that shows the failing and running example can be downloaded from here:
Initialize [NonSerialized] Members
But my question is still un-answered. Why is the local cache member not initialized after de-serializing although I initialized it within the constructor? If someone has an answer to this I would appreciate if he posts a comment.
So have fun
Cheers
Gerhard