The new .NET Reference Source experience

In the last weeks Microsoft has made a series of announcements that will benefit a lot to .NET developers. The first one is the new .NET Reference Source experience. While the http://referencesource.microsoft.com/ site has existed for a while, now it provides new tools to navigate the code like you are used to in Visual Studio (Go To Definition, Find References, etc.). This means that for some scenarios (navigating the code of the .NET Framework assemblies) you don’t need tools such as Reflector .NET or JustDecompile. Of course these tools are still required in many other scenarios, since, for example, the source code of Visual Studio assemblies is not available.

The .NET Reference Source provides also these benefits:

  • You can download the code in a .zip file for off-line browsing.
  • You don’t need a Windows computer to browse the code. A tablet or even a smartphone will work.
  • You have the comments of the source code. Not just the headers, which are
    useless, but the ones inside the methods explaining why some things are
    done in some way (how a bug was fixed, etc.).

For example, last night I used my iPad to browse a couple of things that I was intrigued about:

Years ago I reported a bug in LadyBug (before Microsoft Connect) in the System.Drawing.Color.Equals method. The bug report is no longer available but I remembered that it was related to a comparison of two names that always returned true because the name variable was the same. And yesterday I found it is still there:

public override bool Equals(object obj) {
   if (obj is Color) {
      Color right = (Color)obj;
      if (value == right.value && state == right.state && knownColor == right.knownColor) {
         if (name == right.name) {
            return true;
         }
         if (name == (object) null || right.name == (object) null) {
            return false;
         }
         return name.Equals(name);
      }
   }
   return false;
}

The second one is a tough problem that I was dealing with lately involving COM Reflection (not .NET Reflection). The problem is, given a COM object, how to know its class name (not its interface name). I knew that VB.NET (like VB6 before) has a handy Information.TypeName() method in the Microsoft.VisualBasic assembly, which always seems to return a class name instead of an interface name. Browsing its implementation, I realized that the TypeNameOfCOMObject and LegacyTypeNameOfCOMObject methods are cheating cleaning up the type name:

   Friend Function LegacyTypeNameOfCOMObject(ByVal VarName As Object, ByVal bThrowException As Boolean) As String

      Dim Result As String = COMObjectName

      Try
         Call (New SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Demand()
      Catch ex As StackOverflowException
         Throw ex
      Catch ex As OutOfMemoryException
         Throw ex
      Catch ex As System.Threading.ThreadAbortException
         Throw ex
      Catch e As Exception
         If bThrowException Then
            Throw e
         Else
            GoTo CleanupTypeName
         End If
      End Try

      Dim pTypeInfo As UnsafeNativeMethods.ITypeInfo = Nothing
      Dim hr As Integer
      Dim ClassName As String = Nothing
      Dim DocString As String = Nothing
      Dim HelpContext As Integer
      Dim HelpFile As String = Nothing

      Dim pDispatch As UnsafeNativeMethods.IDispatch = TryCast(VarName, UnsafeNativeMethods.IDispatch)

      If pDispatch IsNot Nothing Then
         hr = pDispatch.GetTypeInfo(0, UnsafeNativeMethods.LCID_US_ENGLISH, pTypeInfo)
         If hr >= 0 Then
            hr = pTypeInfo.GetDocumentation(-1, ClassName, DocString, HelpContext, HelpFile)
            If hr >= 0 Then
               Result = ClassName
            End If
         End If
      End If

CleanupTypeName:

      If Result.Chars(0) = "_"c Then
         Result = Result.Substring(1)
      End If

      Return Result

   End Function

That is, if the name starts with “_” (which likely means it is an interface), the class name that implements that interface is the same name without that character, which can be true sometimes but definitely not most of the time.