概述
调试一个有趣的错误,我剥离了一个解决方案,试图隔离它。该问题表现为典型的构建错误(未引用程序集)。
有趣的是,所讨论的程序集中没有任何类型用于无法构建的程序集中。移动using
语句和删除 CLS 合规性属性会使错误消失,这意味着模糊符号可见性规则(可能)有效。
代码
Mandelbug/
|-- Mandelbug.sln
`-- src
|-- Bar
| |-- Bar.csproj
| `-- Beta.cs
|-- Baz
| |-- Baz.csproj
| |-- Gamma.cs
| `-- Properties
| `-- AssemblyInfo.cs
`-- Foo
|-- Alpha.cs
`-- Foo.csproj
除了项目 ( csproj
) 文件外,此处逐行显示了整个代码库。
Foo/Alpha.cs
namespace Foo {
public class Alpha : Bar.Beta { }
}
酒吧/Beta.cs
namespace Bar {
public class Beta { }
}
Baz/Gamma.cs
namespace Foo {
using System;
public class Gamma { }
}
Baz/Properties/AssemblyInfo.cs
[assembly: System.CLSCompliant(true)]
依赖项
所有项目参考System
和System.Core
.
Baz
参考资料Foo
。
Foo
参考资料Bar
。
Foo.Alpha
需要依赖继承自Bar.Beta
.
Baz.Gamma
在实际解决方案中需要对其他类型的依赖Foo
(与 无关Alpha
)。在这个精简的解决方案中没有使用任何内容,但问题仍然存在。
编译错误
描述:The type 'Bar.Beta' is defined in an assembly that is not referenced. You must add a reference to assembly 'Bar, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
文件:src\Baz\Gamma.cs
行:1
列:11
项目:Baz
行为
在以下情况下问题消失:
- 将
using
语句放在命名空间块Gamma
之外。Foo
- 删除程序集的
CLSCompliant
属性Baz
。 Alpha
不继承自Beta
(即使Foo
仍然引用Bar
并且Alpha
仍然Beta
以其他方式使用,例如通过组合它)。Foo
是遥不可及的Gamma
(例如,通过将Gamma
' 的命名空间更改为Baz
)。Bar
中添加了对 的引用Baz
。
其他项目是否符合 CLS 并不重要。在真正的解决方案中它们是。
目标框架似乎不会影响该行为。
我们在命名空间块中导入什么命名空间并不重要Gamma.cs
,我们在using System;
这里写,但它可以是任何东西。using
如上所述,删除所有语句(或将它们放在命名空间块之外)会使问题消失。
问题
- 什么 CLS 规则会影响该行为?
- 为什么将
using
语句放在命名空间块内部或外部会影响该行为? - 这不仅仅是一个好奇心,我们实际上有一个具有这种传递依赖的项目——我们是否应该添加对的引用,
Bar
即使它没有意义?(我们没有使用Alpha
继承的类型。)
笔记
我知道编译器永远不会出错,但是当您不知道发生了什么(尤其是using
语句放置的事情)时,它仍然看起来像一些严重的巫术。我浏览了 ECMA-335 (CLI) 的 I.11 部分,其中包含 CLS 规则的参考,但我无法确定哪一个是我应该理解的,但显然不是。
如果问题不明显,您应该能够通过简单地在空的 C# 项目中逐字复制代码并添加相同的引用来一致地重现它。