2

概述

调试一个有趣的错误,我剥离了一个解决方案,试图隔离它。该问题表现为典型的构建错误(未引用程序集)。

有趣的是,所讨论的程序集中没有任何类型用于无法构建的程序集中。移动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)]

依赖项

在此处输入图像描述

所有项目参考SystemSystem.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

行为

在以下情况下问题消失:

  1. using语句放在命名空间块Gamma之外。Foo
  2. 删除程序集的CLSCompliant属性Baz
  3. Alpha不继承自Beta(即使Foo仍然引用Bar并且Alpha仍然Beta以其他方式使用,例如通过组合它)。
  4. Foo是遥不可及的Gamma(例如,通过将Gamma' 的命名空间更改为Baz)。
  5. Bar中添加了对 的引用Baz

其他项目是否符合 CLS 并不重要。在真正的解决方案中它们是。
目标框架似乎不会影响该行为。
我们在命名空间块中导入什么命名空间并不重要Gamma.cs,我们在using System;这里写,但它可以是任何东西。using如上所述,删除所有语句(或将它们放在命名空间块之外)会使问题消失。

问题

  1. 什么 CLS 规则会影响该行为?
  2. 为什么将using语句放在命名空间块内部或外部会影响该行为?
  3. 这不仅仅是一个好奇心,我们实际上有一个具有这种传递依赖的项目——我们是否应该添加对的引用,Bar即使它没有意义?(我们没有使用Alpha继承的类型。)

笔记

我知道编译器永远不会出错,但是当您不知道发生了什么(尤其是using语句放置的事情)时,它仍然看起来像一些严重的巫术。我浏览了 ECMA-335 (CLI) 的 I.11 部分,其中包含 CLS 规则的参考,但我无法确定哪一个是我应该理解的,但显然不是。

如果问题不明显,您应该能够通过简单地在空的 C# 项目中逐字复制代码并添加相同的引用来一致地重现它。

4

0 回答 0