CLSCompliant(true)一拖再拖,在未使用的参考文献
-
12-09-2019 - |
题
任何人都可以 解释 以下的行为?
在摘要,如果创建多 符合CLS 图书馆在Visual Studio2008年和他们分享一个共同名字空间的根源、图书馆引用的另一个图书馆 需要 参考图书馆的参考文献,虽然它不会占用他们。
这是很难解释在一个单独的句子,但这里重现步骤的行为(密切关注的名字空间):
创建一个图书馆被称为LibraryA,并添加一个单一类,图书馆:
namespace Ploeh
{
public abstract class Class1InLibraryA
{
}
}
确保图书馆符合CLS通过加入 [assembly: CLSCompliant(true)]
要程序集信息.cs。
另外创建一个图书馆被称为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。突然,解决方案不再编制的,给你这个错误的信息:
类型'Ploeh.Class1InLibraryA'的定义是在一个大会,不是参照。你必须添加一个参考大会'Ploeh,Version=于1.0.0.0、文化=中立的,程序=null'.
你可以做的解决方案汇编在一个以下方式:
- 删除CLS遵守LibraryC
- 增加一个参考LibraryA(虽然你不需要它)
- 改变空间LibraryC,因此,它不是部分的LibraryB的名字空间的层次(例如到Fnaah.样本。LibraryC)
- 改变名字空间的Class1InLibraryB(即,一个 不 使用从LibracyC)因此,它是不会说谎在LibraryC的名字空间的层次(例如到Ploeh.样本。LibraryB)
似乎有一些奇怪的相互作用之间的空间层次和CLS遵守情况。
解决这个问题可以通过挑选的选项之一的名单上,但任何人都可以解释的 的原因 这背后的行为?
解决方案
我已经看到的正式文件CLS(http://msdn.microsoft.com/en-us/netframework/aa569283.aspx的),但是我的头上爆炸之前我能找到一个简单的答案。
但是我认为的基础是编译器,以便验证CLS遵守LibraryC,需要找到可能的命名的冲突与LibraryA.
编译器必须确认所有"零部件的类型,或可见的外部界定大会"(CLS规则1中)。
由于公共类Class1InLibraryC继承Class2InLibraryB,它必须验证CLS遵守对LibraryA,特别是因为"Ploeh.*" 现在是"范围"CLS规则5"所有的名称引入一个符合CLS的范围应当不同的独立的那种".
改变名字空间的Class1InLibraryB或Class1InLibraryC,使他们成为独特的似乎说服的编译器,没有机会为一名冲突了。
如果你选择选项(2),加参考和汇编,你会看到的参考不是实际上的标记在得到大会的元数据,因此这是一个编辑/核查时依赖只。
其他提示
记住,CLS是一套规则,适用于产生的议会和旨在支持之间的互操作性的语言。在某种意义上,它界定最小的共同子集的规则的类型必须遵循确保其语言,和平无关。CLS遵守的也只适用于项目,可见以外的其定义大会。
看一些准则符合CLS码应该遵循:
- 避免使用的名称通常被用作关键词编程语言。
- 不能期望用户的框架内能够作者嵌套的类型。
- 假设实现中的方法相同的姓名和签名不同的接口是独立的。
规则确定CLS遵守:
- 当大会不开展一个明确的系统。CLSCompliantAttribute,它应 假设到开展系统。CLSCompliantAttribute(false)。
- 默认情况下,一类继承的CLS符合属性的封闭类型(嵌套的类型)或获取水平的遵约附于其组件(顶级类型)。
- 默认情况下,其他成员(方法、领域、属性和事件)继承的CLS遵守它们的类型。
现在,作为编译器感到关切的是,(CLS第1条),它必须能够适用的规则CLS遵守的任何信息,将出口之外的组件,并认为一类是符合CLS如果其所有公开访问部分(这些类别、接口、方法领域、性质和活动可执行的代码在另一个组件)要么
- 有签名仅由CLS的类型,或
- 具体标记为不符合CLS。
通过CTS规则,范围是一个简单的集团/集合名称和内范围的一名可参考多个实体只要他们的不同种类(方法、字段嵌套的类型、特性、事件的)或者有不同的签名。一个命名的实体,有它的名字在一个确切的范围,以便确定入口的两个的范围和名称必须加以应用。的范围有资格的名称。
由于类命名的名称的类型也分为范围。充分识别类型、名称必须是合格的范围。类名称作用的组件包含实现这一类型。
用范围,这是符合CLS,所有的名称必须是独特的独立的一种,除非该名称是完全相同,并解决通过载。换句话说,虽然CTS允许一个单一的类型使用的名称相同的一个领域和方法,CLS不(CLS规则第5条)。
采取这一步骤进一步,CLS的类型必须不需要施行不符合CLS类型(CLS规则第20条)和也必须继承另一个CLS的投诉类型(CLS规则23).
一个大会可以依赖于其他组件如果实施范围的一个组件的参考资源范围内在或拥有由另一个组件。
- 所有涉及其他组件得到解决的控制下,当前的大会的范围。
- 它总是能够确定哪些组件的范围的一个具体实施正在运行中。所有请求源自大会范围内解决相对于该范围。
什么所有的这最终意味着,为了验证CLS遵守的类型、编译器必须能够确认 所有 公共部件的类型,也符合CLS。这意味着,它必须确保该名称是唯一的一个范围内,它并不取决于不符合CLS类型自己的部分执行,它继承了其他类型也符合CLS。唯一的方式这样做是通过检查所有的大会类型的参考。
记住,建立一步Visual Studio基本上是一个GUI包围绕执行MSBuild,这最终是没有什么比一个脚本的方法来打电话C#命令行编译器。为了编译器验证CLS遵守的一类,它必须知道的,并能够找到的所有程序集型引用(不是项目)。因为它是所谓通过但这并不说明人们最终Visual Studio,只有这样,才Visual Studio(MSBuild),通知它的那些组件是通过包括它们作为参考。
显然,由于编译器是能够弄清楚,它是"失踪"的参考以核实CLS遵守情况,并汇编成功,那将是好的,如果它可能只包括那些参考上的自动代表我们的。这里的问题是,在确定 哪 版的组件,包括和 哪里 大会在该文件的系统。通过迫使开发商提供信息,编译器有助于保证它给出正确的信息。这也有副作用,确保所有相关组件的复制到 Debug/bin
或 Release/bin
文件夹在建立,使他们在正确的目录应用程序时运行后,已经编制。