Overview
Debugging an interesting bug, I stripped down a solution to its bare bones in an attempt to isolate it. The issue manifests itself with a classic build error (assembly not referenced).
What's interesting is that no types from the assembly in question are used in the assembly that cannot be built. Moving using statements and removing CLS compliance attributes make the error disappear, implying that an obscure symbol visibility rule is in effect (probably).
Code
Mandelbug/
|-- Mandelbug.sln
`-- src
|-- Bar
| |-- Bar.csproj
| `-- Beta.cs
|-- Baz
| |-- Baz.csproj
| |-- Gamma.cs
| `-- Properties
| `-- AssemblyInfo.cs
`-- Foo
|-- Alpha.cs
`-- Foo.csproj
Except for the project (csproj) files, the entire codebase is shown here, line-by-line.
Foo/Alpha.cs
namespace Foo {
public class Alpha : Bar.Beta { }
}
Bar/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)]
Dependencies

All projects reference System and System.Core.
Baz references Foo.
Foo references Bar.
Foo.Alpha needs the dependency to inherit from Bar.Beta.
Baz.Gamma needs the dependency for other types in Foo in the real solution (unrelated to Alpha). None are used in this stripped down solution, yet the issue still appears.
Compilation error
Description: 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'.
File: src\Baz\Gamma.cs
Line: 1
Column: 11
Project: Baz
Behavior
The problem disappears when:
- Placing the
usingstatement inGammaoutside theFoonamespace block. - Removing the
CLSCompliantattribute for theBazassembly. Alphadoes not inherit fromBeta(even ifFoostill referencesBarandAlphastill usesBetain other ways, for example by composing it).Foois out of reach fromGamma(for example by changingGamma's namespace toBaz).- A reference to
Baris added inBaz.
It doesn't matter if the other projects are CLS compliant or not. In the real solution they are.
The target framework doesn't seem to influence that behavior.
It doesn't matter what namespace we import in the Gamma.cs namespace block, we're writing using System; here, but it could be anything. Removing all using statements (or placing them outside the namespace block) makes the problem go away, as mentioned above.
Questions
- What CLS rule affects that behavior?
- Why does placing the
usingstatement inside or outside the namespace block affects that behavior? - This is not just a curiosity, we actually have a project with such a transitive dependency -- should we add the reference to
Bareven though it doesn't make sense? (We're not using theAlphainherited type.)
Notes
I know the compiler is never wrong, but it still looks like some serious voodoo when you don't know what's going on (especially the using statement placement thing). I've skimmed the I.11 section of ECMA-335 (CLI) which contains a reference of CLS rules, but I can't pinpoint which one is the one I should understand but obviously don't.
Should the issue not be obvious, you should be able to reproduce it consistently by simply copying the code verbatim in empty C# projects and adding the same references.