Am not 100% sure, I may be wrong.. I'll propose what I've examined.
Version 2 gets compiled into a func delegate like this new Func<string, Type>(Type.GetType)
Version 3 gets compiled into a compiler generated method in your same class something like this
[CompilerGenerated]
private static Type <Main>b__0(string s)
{
Type type;
type = Type.GetType(s);
Label_0009:
return type;
}
and to a func new Func<string, Type>(Program.<Main>b__0)
So, While executing your enumerator Version2 is just a func
which will be invoked my WhereSelectArrayIterator<TSource, TResult>
private class lives in System.Core.dll
Where as Version3 lives in your assembly.
Coming to the point. If Type.GetType
is invoked with partial names(without fully qualified name) It doesn't knows which assembly the type resides, It gets the calling assembly
and assumes the type lives there.
Hence Version3 lives in your assembly Type.GetType
figured out your type's assembly and scans the assembly fully returns the correct type.
But this is not the case in Version2. You're not actually invoking the Type.GetType
there. It is being invoked by WhereSelectArrayIterator... class
which is in System.Core.dll
. So this assumes your type lives in System.Core.dll
and Type.GetType
fails to find out your type.
Edit:
Following snippet proves above statements were correct
We fake a class in our assembly and name it System.Linq.Expressions.Expression
to see the behavior.
namespace GetTypeTest
{
public class FindMe { }
class Program
{
static void Main(string[] args)
{
var assemblyName = Assembly.GetExecutingAssembly().FullName;
var className = "System.Linq.Expressions.Expression";//"GetTypeTest.FindMe";
var classAndAssembly = string.Format("{0}, {1}", className, assemblyName);
// 1) GetType succeeds when input is "class, assembly", using method group
var result = new[] { classAndAssembly }.Select(Type.GetType).ToArray();
Console.WriteLine("1) Method group & class+assembly: {0}, {1}", result.First(), result.First().Assembly);//your assembly
// 2) GetType fails when input is just the class name, using method group
var result2 = new[] { className }.Select(Type.GetType).ToArray();
Console.WriteLine("2) Method group & class name only: {0}, {1}", result2.First(), result2.First().Assembly);//System.Core assembly
// 3) Identical to (2) except using lamba expression - this succeeds...
var result3 = new[] { className }.Select(s => Type.GetType(s)).ToArray();
Console.WriteLine("3) Lambda expression & class name only: {0}, {1}", result3.First(), result3.First().Assembly);//your assembly
// 4) Method group and core type class name
var result4 = new[] { "System.String" }.Select(Type.GetType).ToArray();
Console.WriteLine("4) Method group for System.String: {0}, {1}", result4.First(), result4.First().Assembly);//mscorlib assembly
Console.ReadLine();
}
}
}
namespace System.Linq.Expressions
{
public class Expression
{
}
}
Outputs
System.Linq.Expressions.Expression [your assembly]
System.Linq.Expressions.Expression [System.Core assembly] since WhereSelectArrayIterator.. belongs to System.Core assembly
System.Linq.Expressions.Expression [your assembly] since compiler generated method belongs to your assembly
System.Linq.Expressions.Expression [mscorlib assembly]
Hope this helps