Search code examples
c#visual-studiolinqextension-methods

Problem with LINQ - necessary to add reference to unneeded library


I have a following issue. I have a solution that contains about 40 projects. There is a project A that references project B that references project C. There isn't any code in project A that uses classes from project C. However, if I use any LINQ extension method in any code, e.g.:

var r = new int[] { 1, 2, 3 }.Where(a => a > 1);

I get compiler error:

somefile.cs(70,13): error CS0012: The type 'XXX' is defined in an assembly that is not referenced. You must add a reference to assembly 'Project C assembly name, Version=0.0.0.0, Culture=neutral, PublicKeyToken=xxx'.

The error is on the line that uses linq extension method.

I'm using VS2010, .NET 3.5.

Update: It happens with every extension method. I have created a class in the same file, that looks like this:

public static class SomeClass
{
    public static int[] Test(this int[] a)
    {
        return a;
    }
}

And then I write this code and compilation breaks with same error:

new int[] { 1, 2, 3 }.Test();

Update2: Ok, I found out what causes the error. But I don't know why. Following code causes error:

using System.Linq;
using B;

namespace TestApp
{
    public class A
    {
        public void M()
        {
            var c = new string[] { "a", "b", "c" }.Where(s => s != null);
        }
    }
}

But if I remove using B (I'm stil following the names from my description that A references B, B references C) it compiles. This is the ONLY code in project A. It compiles if I remove usage of extension method or if I remove "using B" as I said before.

Update3:

First of all, thanks for all your suggestions. The smallest example I can come up with is the following. I created a new project, csproj looks like this (nothing has been changed, only C project name and C project guid):

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>8.0.30703</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{B649AB2C-926A-4AD1-B7E3-5A29AE1E9CC2}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>ClassLibraryTest</RootNamespace>
    <AssemblyName>ClassLibraryTest</AssemblyName>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\C.csproj">
      <Project>{55AFFA2D-63E0-4BA9-XXXX-B70E6A936F5E}</Project>
      <Name>C</Name>
    </ProjectReference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Class1.cs" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="Properties\" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

Class1.cs contains following code:

using C;

namespace TestApp
{
    public static class Ext
    {
        public static void M213dsacxvz(this string[] a)
        {
        }
    }

    public class A
    {
        public void B()
        {
            new string[] { "a", "b", "c" }.M213dsacxvz();
        }
    }
}

The compiler error I get is as follows:

D:\xxx\Class1.cs(16,13): error CS0012: The type 'xxx' is defined in an assembly that is not referenced. You must add a reference to assembly 'xxx, Version=0.0.0.0, Culture=neutral, PublicKeyToken=xxx'.

If I remove using C; it compiles just fine.

Thanks in advance for help.


Solution

  • I found the solution.

    You may download the whole solution (vs 2010) from this link: https://rapidshare.com/files/4269394110/ExtensionProblem.zip.

    I found the complete answer thanks to @Rick Sladkey whose answer was almost complete. The only thing that causes the code to always fail to compile is a constraint on generic method in project B that is specified using class from project C.

    Ok, here is the listing:

    PROJECT A

    ClassA.cs

    using B;
    
    namespace A
    {
        public class ClassA
        {
            public void Foo()
            {
                new int[] { 1, 2, 3 }.ExtMethodC();
            }
        }
    }
    

    If you want the code to compile comment first line (using B;).

    Here is a class that includes random extension method in project A.

    ExtensionsA.cs

    namespace A
    {
        public static class ExtensionsA
        {
            public static void ExtMethodC(this int[] a)
            {
    
            }
        }
    }
    

    PROJECT B

    Extensions.cs - this class has method with generic constraint T : ClassC

    using C;
    
    namespace B
    {
        public static class Extensions
        {
            public static string ExtMethodB<T>(this T cInstance) where T : ClassC
            {
                return cInstance.Foo;
            }
        }
    }
    

    PROJECT C

    ClassC.cs - we need this class to use it in extension method in project B

    namespace C
    {
        public class ClassC
        {
            public string Foo;
        }
    }
    

    For me it looks like a bug in compiler that is too eager to check if extension method in project B may be used in project A.

    Thanks for all your answers! Especially @Rick Sladkey.