Friday, August 31, 2007

C# ‘out’ Parameters: Good or Bad?

VB.NET supports two parameter passing modes: ByVal and ByRef. ByVal indicates changes made to the parameter by the method will not be reflected back to the caller. ByRef indicates changes made to the parameter by the method will be reflected back to the caller.

C# supports three parameter passing modes: ‘in’, ‘ref’, and ‘out’. ‘in’ is the same as the VB.NET ByVal. ‘ref’ is the same as the VB.NET ByRef. ‘out’ indicates the argument does not need to be initialized outside of the method, but this parameter must be set before the method returns.

I recently read two Microsoft articles on C# ‘out’ parameter passing. The first one, written by Peter Hallam, titled “Why does C# have both 'ref' and 'out'?”, explains why C# supports ‘out’ parameter passing and explains why it is a good thing. You can read this article at http://msdn2.microsoft.com/en-us/vcsharp/aa336814.aspx https://web.archive.org/web/20080408140708/http://msdn2.microsoft.com/en-us/vcsharp/aa336814.aspx. The second one, which is really an FxCop rule, titled “Avoid out parameters”, indicates that one should not use ‘out’ parameter passing. You can read this article at http://msdn2.microsoft.com/en-us/library/ms182131(VS.80).aspx.

After reading both articles and doing a little research on my own, I came to the conclusion that the ‘out’ parameter passing mode has its place. Part of this decision was based on the ‘out’ parameter’s usefulness in web service methods. I also decided that I is would be nice if VB.NET had an equivalent parameter passing mode.

The “Avoid out parameters” main argument against using ‘out’ parameters is as follows:
Although return values are commonplace and heavily used, the correct application of out and ref parameters requires intermediate design and coding skills. Library architects designing for a general audience should not expect users to master working with out or ref parameters.

I do not think this is a good reason for not using a language feature. I would like to hear other’s comments on the issue of whether or not using ‘out’ parameters in C# code is a good thing or a bad thing.

Monday, August 27, 2007

Problem with Security Update for Microsoft .NET Framework, Version 2.0 (KB928365)

On July 10, 2007 Microsoft release “Security Update for Microsoft .NET Framework, Version 2.0 (KB928365)”. Unfortunately, this security update has caused some VB.NET software we had written to stop working.

Example Code

Imports System.Xml.Serialization

<System.Serializable()> _
<Xml.Serialization.XmlRoot("SampleData")> _
Public Class SampleData

    Public Sub New()
        mNameList = New List(Of String)
    End Sub

    Private mNameList As List(Of String)
    Public Property NameList() As List(Of String)
        Get
            Return mNameList
        End Get
        Set(ByVal value As List(Of String))
            mNameList = value
        End Set
    End Property

    <XmlIgnore()> _
    Public ReadOnly Property NameListSpecified() As Boolean
        Get
            If mNameList Is Nothing OrElse mNameList.Count < 1 Then
                Return False
            Else
                Return True
            End If
        End Get
    End Property

    Public Overridable Function GetXml() As String

        Dim Buffer As New IO.MemoryStream()
        Dim XmlStreamer As New XmlSerializer(Me.GetType)

        ' Serialize object into XML
        XmlStreamer.Serialize(Buffer, Me)

        ' Encode into String variable
        Return System.Text.Encoding.UTF8.GetString(Buffer.ToArray())

    End Function

End Class

Module Startup

    Sub Main()

        Dim DataObject As New SampleData()

        DataObject.NameList.Add("Name 1")
        DataObject.NameList.Add("Name 2")

        Try
            Console.WriteLine("SampleData as XML:")
            Console.WriteLine(DataObject.GetXml())
        Catch ex As Exception

            Console.Error.WriteLine("The following error occurred:")
            Console.Error.WriteLine(ex.Message)
            Console.Error.WriteLine()
            Console.Error.WriteLine("Error Stack:")
            Console.Error.WriteLine(ex.StackTrace)

        End Try

    End Sub

End Module

Results Pre-KB928365

The following is the output of the sample application above if KB928365 is not installed:

SampleData as XML:
<?xml version="1.0"?>
<SampleData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <NameList>
    <string>Name 1</string>
    <string>Name 2</string>
  </NameList>
</SampleData>

Results Post-KB928365

The following is the output of the sample application if executed on a machine that has KB928365 installed:

SampleData as XML:
The following error occurred:
Unable to generate a temporary class (result=1).
error CS0200: Property or indexer 'XmlSerializationIssueKB928365.SampleData.NameListSpecified' cannot be assigned to -- it is read only

Status as of 07/13/2007

Microsoft has confirmed this is an issue with KB928365. Specifically they have stated the following:
1. Serialization of List<T> fails on Windows 2003 SP2 and Windows XP SP2 after application of Security Patch KB928365.
2. Failure happens only when the project is written in VB.NET. Same code written in C#.NET works.

Microsoft plans to release a hotfix to correct this issue. I will update this posting when that hotfix has been released.

Status as of 07/16/2007

I had the opportunity to discuss this issue with my Microsoft Support contact again today, and we discovered the following:
1. The failure was introduced by KB934529 (which was not widely distributed), but was included as part of KB928365.
2. Changing the NameListSpecified property to writable will workaround the issue.
3. The two items listed in the “Status as of 07/13/2007” section of this article may be incorrect.

I am waiting to hear back as to why this change was made in the .NET 2.0 Framework.

Status as of 07/19/2007

Here is what Microsoft Support had to say about the issue described above:

The reason behind a sudden change in the behavior of serialization / de-serialization was due to a bug identified in the .NET 2.0 version. First let me explain the bug to you. Consider a case where the xxxSpecified property is not marked with [XmlIgnore] and a set method is provided in the code. In that case, the property will look something like this:

Public Property NameListSpecified() As Boolean
   Get
      ‘code
   End Get
   Set(ByVal value As Boolean)
      ‘code
   End Set
End Property

So, when this particular object is serialized, the value of this property will appear in the Xml. In our case, it will appear like this:

   <NameList>
      <string>Name 1</string>
      <string>Name 2</string>
   </NameList>
   <NameListSpecified>true</NameListSpecified>

Everything is fine till now. The problem arises during de-serialization.

During de-serialization, the value of this property should be set as well. You might be aware that XmlSerializer creates dynamic assemblies to accomplish the task of serialization/de-serialization. The code generated during the de-serialization process, in certain cases, did not have the set() method for the property. This was the bug. Hence, the Boolean value used to get set to null, when we were expecting a valid value. This bug was present in .NET 2.0 RTM and was fixed in later updates on System.Xml.dll . (available with hot fixes like 934529, 928365). The fix was in case this property is implemented in code, both the get() and set() has to be provided. You cannot mark this as ReadOnly anymore.

I do fully understand that this scenario is not applicable in our case, as we have attribute tagged with the property. So why should our application break? This has been identified as a valid point. I have had a discussion with the dev team on this as well. They have identified it as another bug induced by a fix. However, they said that since a valid workaround to this is available right now, a fix for this will be provided with .NET 2.0 service pack release. However, a KB article will soon be published by our team acknowledging this break situation with the workaround.

I am waiting to hear back what the KB article number will be and when the .NET 2.0 service pack that contains this fix will be released.

Status as of 08/10/2007

Microsoft sent me a private fix to test against my software yesterday (08/09/2007). The fix was an updated copy of the system.xml.dll (Version 2.0.50727.914). I tested the updated dll against our production code and verified it corrected the issue we were seeing. I will update this posting when the official hotfix is released.

Status as of 08/27/2007

Microsoft contacted me and let me know that KB 941349 (http://support.microsoft.com/?id=941349 https://static.heironimus.info/blog/msdn/941349.html) would be published in a few weeks. This article details the Microsoft .NET Framework 2.0 hotfix that fixes the issue discussed in this article. The version of the system.xml.dll that is included in this hotfix is 2.0.50727.919.