谁能解释以下行为?

总而言之,如果您在Visual Studio 2008中创建多个兼容CLS的库,并让它们共享一个公共(public)的 namespace 根,则引用另一个库的库将需要对该库的引用进行引用,即使它不使用它们。

用一句话很难解释,但是这里是重现行为的步骤(请密切注意 namespace ):

创建一个名为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是在 namespace 中定义的,该 namespace 是LibraryB中定义的 namespace 层次结构的一部分。

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

现在也使LibraryC CLS兼容。突然,解决方案不再编译,出现以下错误消息:



您可以通过以下方式之一重新编译解决方案:
  • 从LibraryC删除CLS合规性
  • 添加对LibraryA的引用(尽管您不需要)
  • 更改LibraryC中的 namespace ,使其不属于LibraryB的 namespace 层次结构(例如Fnaah.Samples.LibraryC)。
  • 更改Class1InLibraryB的 namespace (即LibracyC中未使用的 namespace ),使其不位于LibraryC的 namespace 层次结构中(例如,更改为Ploeh.Samples.LibraryB)。

    似乎在 namespace 层次结构和CLS遵从性之间存在一些奇怪的相互作用。

    解决方案可以通过选择上面列表中的选项之一来解决此问题,但是有人可以解释此现象的原因吗?

    最佳答案

    我查看了CLS的正式文档(http://msdn.microsoft.com/en-us/netframework/aa569283.aspx),但是在找到一个简单答案之前,我的头突然爆炸了。

    但是我认为这样做的基础是,为了验证LibraryC的CLS兼容性,编译器需要研究与LibraryA的可能命名冲突。

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

    由于公共(public)类Class1InLibraryC继承了Class2InLibraryB,因此它还必须验证对LibraryA的CLS遵从性,尤其是因为“Ploeh。*”现在在CLS规则5的“范围内”。种”。

    更改Class1InLibraryB或Class1InLibraryC的 namespace ,使它们变得不同似乎可以说服编译器不再存在名称冲突的机会。

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

  • 09-20 09:56