gpt4 book ai didi

c# - LINQ 的问题 - 有必要添加对不需要的库的引用

转载 作者:可可西里 更新时间:2023-11-01 08:10:12 26 4
gpt4 key购买 nike

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

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

我得到编译器错误:

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'.

错误在使用linq扩展方法的那一行。

我正在使用 VS2010、.NET 3.5。

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

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

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

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

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

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>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 包含以下代码:

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): 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'.

如果我删除using C;,它编译得很好。

在此先感谢您的帮助。

最佳答案

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

ConsoleApplicationA.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
{
}
}

此测试用例产生此错误:

error CS0012: The type 'ClassLibraryC.ClassC' is defined in an assembly that is not referenced. You must add a reference to assembly 'ClassLibraryC, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

编辑:

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

与此同时,一个变通方法是将 B 中的扩展方法放在一个单独的 namespace 中,这些方法在其签名中使用 C 中的类型,并且仅当调用程序集同时引用 B 和 C 时才向该 namespace 添加一个 using 。或者,如果有问题的扩展方法的数量很少并且它们的值(value)有限,您可以移动或删除它们。最后,也是最明显的,您可以完成它并简单地添加对它告诉您应该添加的 C 的引用。

第二次编辑:

警告:我刚刚审查了这个以清理示例,它比我想象的要弱。仅当 A 中调用的扩展方法的名称与 B 中未调用的扩展方法的名称完全匹配时才会失败。例如,如果您将 B 中的 Test 重命名为 NotCalled它不再失败,但在最初的问题中,大概会失败。

最终编辑:

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

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

关于c# - LINQ 的问题 - 有必要添加对不需要的库的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5996514/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com