Can anyone explain the following behavior?
In summary, if you create multiple CLS compliant libraries in Visual Studio 2008 and have them share a common namespace root, a library referencing another library will require references to that library's references even though it doesn't consume them.
It's pretty difficult to explain in a single sentence, but here are steps to reproduce the behavior (pay close attention to the namespaces):
Create a library called LibraryA and add a a single class to that library:
namespace Ploeh
{
public abstract class Class1InLibraryA
{
}
}
Make sure that the library is CLS Compliant by adding [assembly: CLSCompliant(true)]
to AssemblyInfo.cs.
Create another library called LibraryB and reference LibraryA. Add the following classes to LibraryB:
namespace Ploeh.Samples
{
public class Class1InLibraryB : Class1InLibraryA
{
}
}
and
namespace Ploeh.Samples
{
public abstract class Class2InLibraryB
{
}
}
Make sure that LibraryB is also CLS Compliant.
Notice that Class1InLibraryB derives from a type in LibraryA, whereas Class2InLibraryB does not.
Now create a third library called LibraryC and reference LibraryB (but not LibraryA). Add the following class:
namespace Ploeh.Samples.LibraryC
{
public class Class1InLibraryC : Class2InLibraryB
{
}
}
This should still compile. Notice that Class1InLibraryC derives from the class in LibraryB that doesn't use any types from LibraryA.
Also notice that Class1InLibraryC is defined in a namespace that is part of the namespace hierarchy defined in LibraryB.
So far, LibraryC has no reference to LibraryA, and since it uses no types from LibraryA, the solution compiles.
Now make LibraryC CLS compliant as well. Suddenly, the solution no longer compiles, giving you this error message:
The type 'Ploeh.Class1InLibraryA' is defined in an assembly that is not referenced. You must add a reference to assembly 'Ploeh, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
You can make the solution compile again in one of the following ways:
- Remove CLS Compliance from LibraryC
- Add a reference to LibraryA (although you don't need it)
- Change the namespace in LibraryC so that it is not part of LibraryB's namespace hierarchy (e.g. to Fnaah.Samples.LibraryC)
- Change the namespace of Class1InLibraryB (that is, the one not used from LibracyC) so that it is does not lie in LibraryC's namespace hierarchy (e.g. to Ploeh.Samples.LibraryB)
It seems that there is some strange interplay between the namespace hierarchy and CLS compliance.
Solving this issue can be done by picking one of the options in the list above, but can anyone explain the reason behind this behavior?