<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://weblogs.asp.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Omer van Kloeten's .NET Zen : .NET</title><link>http://weblogs.asp.net/okloeten/archive/tags/.NET/default.aspx</link><description>Tags: .NET</description><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><item><title>Circumventing the KB957543 .NET 3.5 SP1 Regression Bug</title><link>http://weblogs.asp.net/okloeten/archive/2009/01/29/6868393.aspx</link><pubDate>Thu, 29 Jan 2009 16:23:18 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6868393</guid><dc:creator>Omer van Kloeten</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/okloeten/rsscomments.aspx?PostID=6868393</wfw:commentRss><comments>http://weblogs.asp.net/okloeten/archive/2009/01/29/6868393.aspx#comments</comments><description>&lt;p&gt;A couple of days ago I hit a regression bug in .NET 3.5 SP1, in which when you have a generic class that implements ISerializable and has static variables – you can not serialize it using a BinaryFormatter without your application either hanging (x86) or raising an exception (x64 – a TargetInvocationException containing an OutOfMemoryException). This only happens if you use a reference type as a generic argument.&lt;/p&gt;  &lt;p&gt;It’s already &lt;a href="http://www.hanselman.com/blog/UpdateOnNETFramework35SP1AndWindowsUpdate.aspx"&gt;well known&lt;/a&gt;, but I have yet to find a workaround documented anywhere. You could simply install the &lt;a href="http://code.msdn.microsoft.com/KB957543"&gt;hotfix&lt;/a&gt;, but well, I wouldn’t if I were you – it hasn’t been thoroughly tested yet. Moreover, you might not even be able to do so due to either internal politics, strict IT rules or the fact that you simply do not have control over the hosting server.&lt;/p&gt;  &lt;p&gt;Let’s take the simplest class that causes the issue:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;code&gt;[&lt;span style="color: #2b91af"&gt;Serializable&lt;/span&gt;]
&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MyClass&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style="color: #2b91af"&gt;ISerializable
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;private static int &lt;/span&gt;list = 0;

    &lt;span style="color: blue"&gt;public &lt;/span&gt;MyClass()
    {
    }

    &lt;span style="color: blue"&gt;protected &lt;/span&gt;MyClass(&lt;span style="color: #2b91af"&gt;SerializationInfo &lt;/span&gt;info, &lt;span style="color: #2b91af"&gt;StreamingContext &lt;/span&gt;context)
    {
    }

    &lt;span style="color: blue"&gt;void &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ISerializable&lt;/span&gt;.GetObjectData(&lt;span style="color: #2b91af"&gt;SerializationInfo &lt;/span&gt;info, &lt;span style="color: #2b91af"&gt;StreamingContext &lt;/span&gt;context)
    {
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When using the class as such:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;code&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;MemoryStream &lt;/span&gt;stream = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MemoryStream&lt;/span&gt;())
{
    &lt;span style="color: #2b91af"&gt;BinaryFormatter &lt;/span&gt;formatter = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;BinaryFormatter&lt;/span&gt;();
    formatter.Serialize(stream, &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MyClass&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;string&lt;/span&gt;&amp;gt;());
    stream.Position = 0;
    &lt;span style="color: #2b91af"&gt;MyClass&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;string&lt;/span&gt;&amp;gt; item = (&lt;span style="color: #2b91af"&gt;MyClass&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;string&lt;/span&gt;&amp;gt;)formatter.Deserialize(stream);
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The last line will hit the bug.&lt;/p&gt;

&lt;p&gt;To work around this issue, simply move your static variables into a new subclass:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;code&gt;[&lt;span style="color: #2b91af"&gt;Serializable&lt;/span&gt;]
&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MyClass&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style="color: #2b91af"&gt;ISerializable
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;private static class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;KB957543
    &lt;/span&gt;{
        &lt;span style="color: blue"&gt;public static int &lt;/span&gt;list = 0;
    }

    &lt;span style="color: blue"&gt;public &lt;/span&gt;MyClass()
    {
    }

    &lt;span style="color: blue"&gt;protected &lt;/span&gt;MyClass(&lt;span style="color: #2b91af"&gt;SerializationInfo &lt;/span&gt;info, &lt;span style="color: #2b91af"&gt;StreamingContext &lt;/span&gt;context)
    {
    }

    &lt;span style="color: blue"&gt;void &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ISerializable&lt;/span&gt;.GetObjectData(&lt;span style="color: #2b91af"&gt;SerializationInfo &lt;/span&gt;info, &lt;span style="color: #2b91af"&gt;StreamingContext &lt;/span&gt;context)
    {
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can still access all of your static variables and you don’t hit the bug.&lt;/p&gt;

&lt;p&gt;Note that when you use anonymous methods or lambdas, they are cached as static variables of the type, meaning that you will have to manually type all of your lambdas.&lt;/p&gt;

&lt;p&gt;Here’s an example of such a type that is prone to the bug:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;code&gt;[&lt;span style="color: #2b91af"&gt;Serializable&lt;/span&gt;]
&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MyClass&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style="color: #2b91af"&gt;ISerializable
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;public &lt;/span&gt;MyClass()
    {
    }

    &lt;span style="color: blue"&gt;public static string &lt;/span&gt;Concat(&lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt; numbers)
    {
        &lt;span style="color: blue"&gt;return string&lt;/span&gt;.Join(&lt;span style="color: #a31515"&gt;&amp;quot;, &amp;quot;&lt;/span&gt;, numbers.Select(i =&amp;gt; i.ToString()).ToArray());
    }

    &lt;span style="color: blue"&gt;protected &lt;/span&gt;MyClass(&lt;span style="color: #2b91af"&gt;SerializationInfo &lt;/span&gt;info, &lt;span style="color: #2b91af"&gt;StreamingContext &lt;/span&gt;context)
    {
    }

    &lt;span style="color: blue"&gt;void &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ISerializable&lt;/span&gt;.GetObjectData(&lt;span style="color: #2b91af"&gt;SerializationInfo &lt;/span&gt;info, &lt;span style="color: #2b91af"&gt;StreamingContext &lt;/span&gt;context)
    {
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we look through Reflector, we can see that there is a cached delegate in our type:&lt;/p&gt;

&lt;p&gt;&lt;img title="" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="186" alt="" src="http://weblogs.asp.net/blogs/okloeten/image_292AD855.png" width="589" border="0" /&gt; &lt;/p&gt;

&lt;p&gt;Since this is a static member, it makes the type susceptible to the bug and we now need to manually create the cached member ourselves:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;code&gt;[&lt;span style="color: #2b91af"&gt;Serializable&lt;/span&gt;]
&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MyClass&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style="color: #2b91af"&gt;ISerializable
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;private static class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;KB957543
    &lt;/span&gt;{
        &lt;span style="color: blue"&gt;public static readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;, &lt;span style="color: blue"&gt;string&lt;/span&gt;&amp;gt; ToString = i =&amp;gt; i.ToString();
    }

    &lt;span style="color: blue"&gt;public &lt;/span&gt;MyClass()
    {
    }

    &lt;span style="color: blue"&gt;public static string &lt;/span&gt;Concat(&lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt; numbers)
    {
        &lt;span style="color: blue"&gt;return string&lt;/span&gt;.Join(&lt;span style="color: #a31515"&gt;&amp;quot;, &amp;quot;&lt;/span&gt;, numbers.Select(&lt;span style="color: #2b91af"&gt;KB957543&lt;/span&gt;.ToString).ToArray());
    }

    &lt;span style="color: blue"&gt;protected &lt;/span&gt;MyClass(&lt;span style="color: #2b91af"&gt;SerializationInfo &lt;/span&gt;info, &lt;span style="color: #2b91af"&gt;StreamingContext &lt;/span&gt;context)
    {
    }

    &lt;span style="color: blue"&gt;void &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ISerializable&lt;/span&gt;.GetObjectData(&lt;span style="color: #2b91af"&gt;SerializationInfo &lt;/span&gt;info, &lt;span style="color: #2b91af"&gt;StreamingContext &lt;/span&gt;context)
    {
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6868393" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/okloeten/archive/tags/How+To/default.aspx">How To</category><category domain="http://weblogs.asp.net/okloeten/archive/tags/Advices/default.aspx">Advices</category><category domain="http://weblogs.asp.net/okloeten/archive/tags/.NET/default.aspx">.NET</category></item></channel></rss>