LINQ 问题 - 添加对不需要的库的引用是必需的



我有以下问题。我有一个包含大约 40 个项目的解决方案。有一个项目 A 引用了引用项目 C 的项目 B。项目 A 中没有任何代码使用项目 C 中的类。但是,如果我在任何代码中使用任何 LINQ 扩展方法,例如:

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

我收到编译器错误:

somefile.cs(70,13): 错误 CS0012: 类型"XXX"在未引用的程序集中定义。必须添加对程序集"项目 C 程序集名称,版本=0.0.0.0,区域性=中性,公钥令牌=xxx"的引用。

错误位于使用 linq 扩展方法的行上。

我正在使用VS2010,.NET 3.5。

更新:每个扩展方法都会发生这种情况。我在同一个文件中创建了一个类,如下所示:

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

然后我写了这段代码,编译中断了同样的错误:

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

更新2:好的,我找到了导致错误的原因。但我不知道为什么。以下代码导致错误:

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

但是,如果我使用 B 删除(我遵循我的描述中的名称,A 引用 B,B 引用 C),它会编译。这是项目 A 中唯一的代码。如果我删除扩展方法的使用或删除我之前所说的"使用 B",它会编译。

更新3:

首先,感谢您的所有建议。我能想到的最小的例子如下。我创建了一个新项目,csproj 看起来像这样(没有任何更改,只有 C 项目名称和 C 项目 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>binDebug</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>binRelease</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 包含以下代码:

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();
        }
    }
}

我得到的编译器错误如下:

D:\xxx\Class1.cs(16,13):错误 CS0012:类型"xxx"在未引用的程序集中定义。必须添加对程序集"xxx, 版本=0.0.0.0, 区域性=中性, 公钥令牌=xxx"的引用。

如果我删除using C;它可以很好地编译。

提前感谢您的帮助。

下面是一个重现该问题的小示例。 它是由 B 中的扩展方法引起的,该方法在其签名中使用 C 中定义的类型。 即使未使用扩展方法,错误也会由搜索可通过 using 访问的所有扩展方法的过程触发。

控制台应用程序A.cs:

using ClassLibraryB;
namespace ConsoleApplication1
{
    public static class Extensions
    {
        public static int Test(this int a)
        {
            return a;
        }
    }
    public class ProgramA
    {
        static void Main(string[] args)
        {
            0.Test();
        }
    }
}

类库B.cs:

using ClassLibraryC;
namespace ClassLibraryB
{
    public static class Extensions
    {
        public static ClassC Test(this ClassB b)
        {
            return new ClassC();
        }
    }
    public class ClassB
    {
    }
}

类库C.cs:

namespace ClassLibraryC
{
    public class ClassC
    {
    }
}

此测试用例产生此错误:

错误 CS0012:类型"类库C.类C"在未引用的程序集中定义。必须添加对程序集"ClassLibraryC, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"的引用。

编辑:

在我看来,这是 C# 编译器中的一个错误,因为对于您未引用的方法来说,它会导致程序编译失败,这是非常令人惊讶的行为。 C# 编译器团队可能有不同的看法。

同时,解决方法是将签名中使用 C 中的类型的扩展方法放在 B 中,并仅在调用程序集同时引用 B 和 C 时才向该命名空间添加 using 。 或者,如果违规扩展方法的数量很少且其值有限,则可以移动或删除它们。 最后,也是最明显的,你可以完成它,只需添加它告诉你应该添加的对 C 的引用。

第二次编辑:

警告:我刚刚审查了这个来清理这个例子,它比我想象的要弱。 仅当 A 中调用的扩展方法的名称与 B 中未调用的扩展方法的名称完全匹配时,它才会失败。 因此,例如,如果您重命名 B 中的 TestNotCalled它不再失败,但在原始问题中,大概它会失败。

最终编辑:

通过合作,我们缩小了重现原始问题中描述的问题的必要条件:B 中的扩展方法,其签名中来自 C 的类型使用泛型类型约束。 上面的测试用例是一个更窄的例子。 具体条件显然与编译器搜索扩展方法的方式的具体实现有关。

总之,引用是运行时功能,扩展方法是编译时功能。 无论错误消息是如何生成的,如果未调用该方法,编译器就是在编译时需要引用的编译器,程序集在运行时不需要引用。 因此,错误不是编译器别无选择,而是发出,这只是编译器的不便情况。

我找到了解决方案。

您可以从以下链接下载整个解决方案(与 2010 年相比):https://rapidshare.com/files/4269394110/ExtensionProblem.zip。

多亏了@Rick Sladkey,我找到了完整的答案。导致代码始终无法编译的唯一原因是对项目 B 中泛型方法的约束,该方法是使用项目 C 中的类指定的。

好的,这是列表:

项目 A

A类.cs

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

如果希望代码编译注释第一行(using B;)。

下面是一个在项目 A 中包含随机扩展方法的类。

扩展A.cs

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

项目 B

扩展.cs - 此类具有具有泛型约束的方法T : ClassC

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

项目 C

ClassC.cs - 我们需要这个类在项目 B 的扩展方法中使用它

namespace C
{
    public class ClassC
    {
        public string Foo;
    }
}
对我来说,它

看起来像编译器中的一个错误,它太急于检查项目 B 中的扩展方法是否可以在项目 A 中使用。

感谢您的所有回答!尤其是@Rick斯拉德基。

在我看来

,最有可能的答案是IEnumerableIEnumrable<T>上有一种扩展方法,称为B中的Where。此扩展方法使用 C 中的类型(作为返回类型?或类型约束?),这需要您引用它。

Visual Studio告诉你Where是什么?

至于解决方案,似乎B在您的控制之下,因此您应该删除扩展方法,它真的不应该存在。作为替代解决方案,您可以使用长语法:Enumerable.Where(collection, s => s != null) .

相关内容

  • 没有找到相关文章

最新更新