谁能解释以下行为?
总而言之,如果您在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兼容。突然,解决方案不再编译,出现以下错误消息:
您可以通过以下方式之一重新编译解决方案:
似乎在 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),则添加引用并进行编译,您将看到在生成的程序集元数据中未实际标记该引用,因此,这仅是编译/验证时的依赖项。