.net - CLSCompliant(true) 拖入未使用的引用

标签 .net visual-studio-2008 reference namespaces cls-compliant

谁能解释以下行为?

总而言之,如果您在 Visual Studio 2008 中创建多个符合 CLS 的库并让它们共享一个公共(public)命名空间根,则引用另一个库的库将需要引用那个库的引用,即使它不使用它们。

这很难用一句话来解释,但这里有重现该行为的步骤(请密切注意命名空间):

创建一个名为 LibraryA 的库并向该库添加一个类:

namespace Ploeh
{
    public abstract class Class1InLibraryA
    {
    }
}

通过将 [assembly: CLSCompliant(true)] 添加到 AssemblyInfo.cs,确保该库符合 CLS。

创建另一个名为 LibraryB 的库并引用 LibraryA。将以下类添加到 LibraryB:

namespace Ploeh.Samples
{
    public class Class1InLibraryB : Class1InLibraryA
    {
    }
}

namespace Ploeh.Samples
{
    public abstract class Class2InLibraryB
    {
    }
}

确保 LibraryB 也符合 CLS。

请注意,Class1InLibraryB 派生自 LibraryA 中的类型,而 Class2InLibraryB 则不是。

现在创建名为 LibraryC 的第三个库并引用 LibraryB(但不是 LibraryA)。添加以下类:

namespace Ploeh.Samples.LibraryC
{
    public class Class1InLibraryC : Class2InLibraryB
    {
    }
}

这应该仍然可以编译。请注意,Class1InLibraryC 派生自 LibraryB 中的类,不使用 LibraryA 中的任何类型

另请注意,Class1InLibraryC 是在一个命名空间中定义的,该命名空间是 LibraryB 中定义的命名空间层次结构的一部分。

到目前为止,LibraryC 没有对 LibraryA 的引用,并且由于它没有使用 LibraryA 中的类型,因此解决方案可以编译。

现在也让 LibraryC CLS 兼容。突然,解决方案不再编译,给你这个错误信息:

The type 'Ploeh.Class1InLibraryA' is defined in an assembly that is not referenced. You must add a reference to assembly 'Ploeh, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

您可以通过以下方式之一使解决方案再次编译:

  • 从 LibraryC 中移除 CLS 合规性
  • 添加对 LibraryA 的引用(尽管您不需要它)
  • 更改 LibraryC 中的 namespace ,使其不属于 LibraryB 的 namespace 层次结构(例如更改为 Fnaah.Samples.LibraryC)
  • 更改 Class1InLibraryB 的 namespace (即,从 LibracyC 使用的 namespace ),使其不在 LibraryC 的 namespace 层次结构中(例如 Ploeh.Samples.LibraryB)

命名空间层次结构和 CLS 合规性之间似乎存在一些奇怪的相互作用。

可以通过选择上面列表中的一个选项来解决这个问题,但是谁能解释这种行为背后的原因

最佳答案

我查看了 CLS 的官方文档 ( http://msdn.microsoft.com/en-us/netframework/aa569283.aspx ),但在我找到一个简单的答案之前我的脑袋爆炸了。

但我认为基础是编译器为了验证 LibraryC 是否符合 CLS,需要调查与 LibraryA 可能存在的命名冲突。

编译器必须验证所有“在定义程序集之外可访问或可见的类型部分”(CLS 规则 1)。

由于公共(public)类 Class1InLibraryC 继承了 Class2InLibraryB,它还必须针对 LibraryA 验证 CLS 合规性,特别是因为“Ploeh.*”现在在 CLS 规则 5 的“范围内”“在符合 CLS 的范围内引入的所有名称应独立于种类”。

更改 Class1InLibraryB 或 Class1InLibraryC 的命名空间以使它们变得不同似乎可以说服编译器不再有名称冲突的机会。

如果您选择选项 (2),添加引用并编译,您将看到引用实际上并未标记在生成的程序集元数据中,因此这只是一个编译/验证时依赖性。

关于.net - CLSCompliant(true) 拖入未使用的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24700730/

相关文章:

.Net:如何使用 TypeDescriptor.GetProperties 获取自定义属性?

c# - 引用外部 dll 时由于某些元组错误而无法编译 c# 项目

c# - 如何增加原始音频字节的音量/振幅

asp.net - 了解站点是在 Release模式还是 Debug模式下发布的

database - 如何在 Visual Studio 2008 中连接到 Access 2007 (accdb) 文件

c# - 如何将外部非 Windows Phone 类库项目引用添加到 Windows Phone 项目?

c++ - 神秘的相对路径库依赖

c++ - 使用引用传递字符串需要进行哪些必要的更改

c# - 实例化之后是赋值编译,但是

perl - 如何在 Perl 中使用代码引用作为回调?