7

In resolving the question

Error Loading ASP.Net Profile

I came across behavior of Type.GetType(string typeName) that I do not understand.

When getting the type of a List<int>, it is sufficient to specify the type as

System.Collections.Generic.List`1[[System.Int32]]

However, for HashSet<int>, I must specify a fully qualified type name like this

System.Collections.Generic.HashSet`1[[System.Int32]], System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

If I leave out any of the assembly, version, culture, or public key token, the type is not resolved.

Code to reproduce

// Returns expected type:
Type tListWorks = 
     Type.GetType("System.Collections.Generic.List`1[[System.Int32]]");

// Returns null:
Type tHashSetNull = 
     Type.GetType("System.Collections.Generic.HashSet`1[[System.Int32]]");

// Returns expected type:
Type tHashSetWorks = 
     Type.GetType("System.Collections.Generic.HashSet`1[[System.Int32]], System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");

// Returns null (omitted Culture):
Type tHashSetNoCultureFails = 
     Type.GetType("System.Collections.Generic.HashSet`1[[System.Int32]], System.Core, Version=4.0.0.0, PublicKeyToken=b77a5c561934e089");

Questions

  • Why must I fully qualify HashSet<T> but not List<T>?
  • Given that the Version qualification must be specified, what if the .NET Runtime is 3.5 (first one that had HashSet<T>) or a later one such as .NET 4.5? What if the runtime is something else entirely like Silverlight or Mono?
Community
  • 1
  • 1
Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • This should also work (though I haven't tried): `System.Collections.Generic.HashSet`1[[System.Int32]], System.Core` – Andrey Shchekin Jul 27 '12 at 05:55
  • @Andrey: That was my expectation too, but that does not work. – Eric J. Jul 27 '12 at 05:56
  • this might be relevant: http://stackoverflow.com/a/2367674/39068 – Andrey Shchekin Jul 27 '12 at 06:00
  • I quickly tried short version in F# Interactive (works), and in PowerShell and Roslyn (does not work). F# Interactive has given me `Binding session to 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Core.dll'...`. Since it obviously does not parse strings, I used some Reflector and, as expected, it installs custom `AppDomain.CurrentDomain.AssemblyResolve`. So it should be possible to specify a shorter name if you use a custom assembly resolver that allows shorter names. – Andrey Shchekin Jul 27 '12 at 12:59

1 Answers1

5

List<T> is defined in mscorelib, HashSet<T> is not.

As per the documentation:

If the type is in the currently executing assembly or in Mscorlib.dll, it is sufficient to supply the type name qualified by its namespace

As for your second question, if you provide a qualified type name to an assembly that is not available in the current framework/profile, GetType will return null.

The reason behind requiring all the assembly attributes is specified in the Type.GetType documentation (as pointed out by Jason Malinowski in the comments):

If typeName includes the namespace but not the assembly name, this method searches only the calling object's assembly and Mscorlib.dll, in that order. If typeName is fully qualified with the partial or complete assembly name, this method searches in the specified assembly. If the assembly has a strong name, a complete assembly name is required.

Richard Szalay
  • 83,269
  • 19
  • 178
  • 237
  • Yes, but qualifying **just with the assembly** does not work. I have to qualify with the assembly, version, culture and public key token. – Eric J. Jul 27 '12 at 05:53
  • The full "name" of the assembly includes the Version, Culture, etc, attributes. – Jason Malinowski Jul 27 '12 at 06:01
  • @Jason: Following the documentation further, *The assembly-qualified name of a type consists of the type name, including its namespace, followed by a comma, followed by the display name of the assembly.* No mention that Culture etc. are needed http://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname.aspx – Eric J. Jul 27 '12 at 06:01
  • Eric is right. According to [Specifying Fully Qualified Type Names](http://msdn.microsoft.com/en-us/library/yfsftwz6.aspx), the assembly name alone should be sufficient. Unfortunately, I'm not sure why it doesn't work here. – Richard Szalay Jul 27 '12 at 06:07
  • 2
    Reading through the docs for Type.GetType(string), it states: "If typeName is fully qualified with the partial or complete assembly name, this method searches in the specified assembly. _If the assembly has a strong name, a complete assembly name is required._" System.Core.dll would have a strong name, so maybe this rule applies no matter what. – Jason Malinowski Jul 27 '12 at 06:14
  • @JasonMalinowski - You should add that as a separate answer as that looks like the culprit. – Richard Szalay Jul 27 '12 at 06:15
  • @RichardSzalay: I'll verify it tomorrow before officially stating that it's the case. :-) – Jason Malinowski Jul 27 '12 at 06:17
  • @JasonMalinowski: I'll leave the question open for a bit so you can verify. Certainly +1 to Richard as well. – Eric J. Jul 27 '12 at 06:19