0

I'm writing a program in Visual Studio 2012, and I have a pair of classes in two separate projects:

ProjectA:

namespace Test
{
  internal class A
  {
    private A(B b)
    {
      Contract.Requires(b.X != null);
    }
  }
}

ProjectB:

namespace Test
{
  internal class B
  {
    public string X;
  }
}

In AssemblyInfo.cs in ProjectB, I also have:

[assembly: InternalsVisibleTo("ProjectA")]

This compiles just fine until I turn on CodeContract static analysis. At this point, I get an error from ccrewrite: Member 'Test.B.X' has less visibility than the enclosing method Test.A.#ctor(Test.B).

The only thing that I can think might be causing the problem is that CodeContracts doesn't know that ProjectA can see ProjectB's internals, and thus believes that class B's visibility is essentially none with this context. Although if I change the assertion to b != null, it seems to be fine, so maybe this argument doesn't hold water.

Can anyone confirm this assertion, or give me a correct explanation, and short of removing the Requires, turning off CodeContracts or changing the visibility of B, is there a way around this error?

Philip C
  • 1,819
  • 28
  • 50

1 Answers1

1

Code contract does not know the meaning of the attribute:

[assembly: InternalsVisibleTo("ProjectA")]

So it does not know that the interals are visible to projectA. InternalsVisibleToAttribute is designed to ease unittesting.

You should think about why you are seprating the two classes in different assamblies when they need to know each other. Maybe you can solve it with a interface, and some sort of factory.

Peter
  • 27,590
  • 8
  • 64
  • 84
  • ProjectB is a thin C++/CLI wrapper around a native API, and ProjectA is a number of bits and pieces that use it. The idea is to have ProjectA able to use ProjectB as if it were the same assembly, and merge them with ILMerge afterwards to form a single assembly to be used by other projects. I wasn't aware that unit testing was the original purpose for the InternalsVisibleTo attribute. Maybe I'll have a rethink. – Philip C Oct 29 '13 at 14:54
  • Also, why would CodeContracts allow the requirement `b != null`? What makes that legal where `b.X != null` isn't? – Philip C Oct 29 '13 at 14:56
  • @PhilipC an code contract assertion is a different check as a requires, assertions are just compiled into the code. Requires are used for checking at compile time. – Peter Oct 29 '13 at 15:20
  • @PhilipC : "What makes that legal where...." -> b != null is just a reference check. b.X != null implies that the code needs to have access to X (and by that to the whole class definition) and it sees that as not accessible. – Adrian Zanescu Oct 29 '13 at 16:27