4

I have a scenario where the compiler is complaining that i am missing a needed reference.

I have 3 assemblies:

  • A.DLL

    • public class BaseClass
  • B.DLL (References A.DLL)

    • public class DerivedClass : BaseClass
  • C.DLL

    var derived = new DerivedClass();

In C.DLL i am only referencing B.DLL (i need access to DerivedClass only).

The compiler gives an error, saying i need to also reference A.DLL

This completely breaks the encapsulation, and i am not sure why this is needed (since B.DLL references A.DLL).

EDIT: Bad choice of words on "breaking encapsulation". My intention was this causes what seems to be an additional compile-time constraint on this project (C.DLL) since i am only instantiating types from B.DLL, and not from A.DLL.

I would want this compile-time requirement to be removed, mostly because B and C sit in the same solution, but A does not.

lysergic-acid
  • 19,570
  • 21
  • 109
  • 218

2 Answers2

7

This completely breaks the encapsulation, and i am not sure why this is needed (since B.DLL references A.DLL).

I don't see how it "completely breaks the encapsulation".

In order to perform member resolution, the compiler needs to know what's in BaseClass. Therefore to compile C.dll, you need references to both A.dll and B.dll. When someone is writing code accessing an instance of DerivedClass, they need to know what BaseClass supports, as it's likely to be a super-set of what DerivedClass itself overrides.

Even if you don't like it, that's just the way it is. If you don't want A.dll to be required at compile-time you could use composition instead of inheritance - but you'll still need A.dll at execution-time anyway.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Agree. In C you know that DerivedClass is derived from BaseClass anyway. Now C needs to how BaseClass is defined. – EricSchaefer Jul 23 '12 at 07:27
  • You are right :) bad choice of words from my side. The thing i wanted to exactly say was this is bad for me AT COMPILE TIME. At runtime i don't mind both assemblies will be needed. – lysergic-acid Jul 23 '12 at 07:29
  • @lysergic-acid: Even though you're only *instantiating* a type from `B.dll`, you still need to know about the type it inherits from, to know what members are available. Why is this "bad for you" at compile time? It's basically unavoidable, and I think it's entirely reasonable. – Jon Skeet Jul 23 '12 at 08:02
  • @JonSkeet i have edited my question. The problem is A.dll is not in the same solution as both other projects. The easy solution would be to include it, but i have the same scenario with other projects, leading to a "master .sln file" with bazillion projects in it... – lysergic-acid Jul 23 '12 at 08:22
  • Maybe this changed in later C# versions, but I just tried, and I CAN instantiate `DerivedClass` in `C.DLL` (following OP's example). I can not use methods of `DerivedClass` (even if they do nothing with `BaseClass`), BUT I can use properties of `DerivedClass` even if they use above mentioned method or stuff from `BaseClass`. Now I'm properly confused! – v01pe Jun 30 '21 at 10:49
  • @v01pe: I'd need a lot more detail to be able to comment, really - but I would note that the .NET tooling (not the language) has changed over the years to support transitive dependencies more simply. – Jon Skeet Jun 30 '21 at 10:56
  • Thanks @JonSkeet, that was just another missing link in the puzzle I had to solve and it's not essential :) I had a really hard time to formulate a search that lead me to an answer for my problem, but finally found it here: https://stackoverflow.com/q/51547053/1050264 – v01pe Jun 30 '21 at 11:17
2

Blockquote This completely breaks the encapsulation, and i am not sure why this is needed (since B.DLL references A.DLL).

I see you've revised this choice of words, but I think I understand what you meant. If you want to ensure A can only use C via B, you'd like to reference B but not C from A.

I do understand that the compiler needs to use both B and C, but what I don't understand is why it cannot do resolution based on the reference from A to B and the one from B to C. It seems to me if I've told you "B depends on C" and "A depends on B", you can infer that A also depends on C.

If the build could resolve types by following the dependency graph it seems to me you wouldn't have to resort to interfaces whenever you want to use references to enforce a particular layering of code. I don't know how else to do it, but interfaces are just a burden in cases where you really just want one implementation, so I wish this sort of thing was possible.

The Dag
  • 1,811
  • 16
  • 22