Today I migrated a C#/WPF project in Visual Studio 2010 from .NET 3.5 SP1 to .NET 4.0. Immediately the compile failed issuing this set of errors:
- The predefined type ‘System.Func’ is defined in multiple assemblies in the global alias; using definition from ‘c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll’
- The predefined type ‘System.Func’ is defined in multiple assemblies in the global alias; using definition from ‘c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Core.dll’
To resolve this error involved understanding a little bit more about C#, .NET, and the Common Language Runtime (CLR).
According to C# 4.0 In A Nutshell from O’Reilly Press, on page 181 it says:
Some of the .NET types are used directly by the CLR and are essential for the managed hosting environment. These types reside in an assembly called mscorlib.dll and include C#’s built in types, ….
At a level above this are additional types that “flesh out” the CLR-functionality, …. These reside in System.dll, System.Xml.dll, and System.Core.dll, and together with mscorlib the provide a rich programming environment….
So mscorlib and System.Core are both needed. This begs the question, why is Func declared in both and thus causing a conflict? Or is it?
Further on in C# 4.0 In A Nutshell from O’Reilly Press, on page 183 in a general note it says:
A notable exception is the following types, which Framework 4.0 have moved from System.Core to mscorlib.dll:
- The Action and Func delegates
- …
This suggests a case exists where mscorlib is from our current .NET (the later one has Func), and System.Core is coming from the old one (which is where Func lives for that version).
How is this possible? It’s our projects fault.
This question on StackOverflow provides some insight; check out Simon‘s answer.
- Right-click the project and select Unload Project
- Right-click the project again and select Edit Project
- Scroll down in the XML to find the ItemGroup element; it’ll have Reference elements insider of it.
- Locate the Reference element that has Include=”System.Core” as an attribute.
- If it has other qualifiers, remove them. If it has a TargetFrameworkVersion subelement remove it.
- Save the XML.
- Right-click the project and reload it; try a build now.
In my case, I had an entry that looked like this:
<Reference Include=”System.Core”>
<TargetFrameworkVersion>3.5</TargetFrameworkVersion>
</Reference>
</ItemGroup>
Removing the TargetFrameworkVersion, shown in red above, un-pinned the dll from the older .NET framework and things worked just fine.