CLSCompliant(true) 拖入未使用的引用 [英] CLSCompliant(true) drags in unused references

查看:13
本文介绍了CLSCompliant(true) 拖入未使用的引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谁能解释以下行为?

总而言之,如果您在 Visual Studio 2008 中创建多个CLS 兼容库并让它们共享一个公共命名空间根,则引用另一个库的库将要求引用该库库的引用,即使它不使用它们.

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

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

命名空间 Ploeh{公共抽象类 Class1InLibraryA{}}

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

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

命名空间 Ploeh.Samples{公共类 Class1InLibraryB : Class1InLibraryA{}}

命名空间 Ploeh.Samples{公共抽象类 Class2InLibraryB{}}

确保 LibraryB 也符合 CLS.

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

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

命名空间 Ploeh.Samples.LibraryC{公共类 Class1InLibraryC : Class2InLibraryB{}}

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

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

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

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

<块引用>

类型Ploeh.Class1InLibraryA"是在未引用的程序集中定义的.您必须添加对程序集Ploeh, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"的引用.

您可以通过以下方式之一重新编译解决方案:

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

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

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

解决方案

我查看了 CLS 的官方文档 (http://msdn.microsoft.com/en-us/netframework/aa569283.aspx),但我还没来得及找到一个简单的答案,我的脑袋就炸了.

但我认为基础是编译器为了验证LibraryC是否符合CLS,需要研究可能与LibraryA的命名冲突.

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

由于公共类 Class1InLibraryC 继承了 Class2InLibraryB,它也必须验证与 LibraryA 的 CLS 合规性,特别是因为Ploeh.*"现在在 CLS 规则 5在 CLS 兼容范围中引入的所有名称都应在范围内"独立于种类".

更改 Class1InLibraryB 或 Class1InLibraryC 的命名空间,使它们变得不同似乎可以说服编译器不再发生名称冲突.

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

Can anyone explain the following behavior?

In summary, if you create multiple CLS compliant libraries in Visual Studio 2008 and have them share a common namespace root, a library referencing another library will require references to that library's references even though it doesn't consume them.

It's pretty difficult to explain in a single sentence, but here are steps to reproduce the behavior (pay close attention to the namespaces):

Create a library called LibraryA and add a a single class to that library:

namespace Ploeh
{
    public abstract class Class1InLibraryA
    {
    }
}

Make sure that the library is CLS Compliant by adding [assembly: CLSCompliant(true)] to AssemblyInfo.cs.

Create another library called LibraryB and reference LibraryA. Add the following classes to LibraryB:

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

and

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

Make sure that LibraryB is also CLS Compliant.

Notice that Class1InLibraryB derives from a type in LibraryA, whereas Class2InLibraryB does not.

Now create a third library called LibraryC and reference LibraryB (but not LibraryA). Add the following class:

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

This should still compile. Notice that Class1InLibraryC derives from the class in LibraryB that doesn't use any types from LibraryA.

Also notice that Class1InLibraryC is defined in a namespace that is part of the namespace hierarchy defined in LibraryB.

So far, LibraryC has no reference to LibraryA, and since it uses no types from LibraryA, the solution compiles.

Now make LibraryC CLS compliant as well. Suddenly, the solution no longer compiles, giving you this error message:

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

You can make the solution compile again in one of the following ways:

  • Remove CLS Compliance from LibraryC
  • Add a reference to LibraryA (although you don't need it)
  • Change the namespace in LibraryC so that it is not part of LibraryB's namespace hierarchy (e.g. to Fnaah.Samples.LibraryC)
  • Change the namespace of Class1InLibraryB (that is, the one not used from LibracyC) so that it is does not lie in LibraryC's namespace hierarchy (e.g. to Ploeh.Samples.LibraryB)

It seems that there is some strange interplay between the namespace hierarchy and CLS compliance.

Solving this issue can be done by picking one of the options in the list above, but can anyone explain the reason behind this behavior?

解决方案

I had a look into the official documents for the CLS (http://msdn.microsoft.com/en-us/netframework/aa569283.aspx), but my head exploded before I could find a simple answer.

But I think the basis is that the compiler, in order to verify the CLS compliance of LibraryC, needs to look into possible naming conflicts with LibraryA.

The compiler must verify all "parts of a type that are accessible or visible outside of the defining assembly" (CLS Rule 1).

Since public class Class1InLibraryC inherits Class2InLibraryB, it must verify the CLS compliance against LibraryA as well, in particular because "Ploeh.*" is now "in scope" for CLS Rule 5 "All names introduced in a CLS-compliant scope shall be distinct independent of kind".

Changing either the namespace of Class1InLibraryB or Class1InLibraryC so they become distinct seems to convince the compiler there is no chance for a name conflict anymore.

If you choose option (2), add the reference and compile, you'll see that the reference is not actually marked in the resulting assembly meta-data, so this is a compilation/verification-time dependency only.

这篇关于CLSCompliant(true) 拖入未使用的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆