What is a circular dependency and how can I solve it?
Asked Answered
R

4

24

Scenario


I have a solution on which I have (more than) 2 projects.

The first project has a project reference to the second project. The second project doesn't have a reference to the first project.

Well, in the first project I defined a inheritable class-type on which I would like that some classes from the second project inherits from it.

Problem


Obviouslly, If I want to inherit the type defined in the first project, in the second project I need to add a project reference to the first project to be able see the type and go on.

The problem is that when I try to add the project reference, I get this error message:

Circular dependency error

Question


Someone could explain me with other simple words (maybe with a code example too in case of code is implied in the error) what is a circular dependency?, and the most important thing: what can I do to solve it? (please read the last prhases of my research before answering).

Research


Is the first time that I hear the term "Circular dependency"; I've read this article from MSDN but I understood nothing.

Anyways I seen many questions of circular dependencys like this, and from what I've seen in that question seems that a circular dependency means that two projects cannot reference between them at the same time, just one of those two projects can reference the other; and also all the people who answered in that question said things like "Re-design is the solution" or "Circular dependencies are not good practices", however, re-designing in my case will mean define the same type in both projects, which I don't think that could be good practices neither, and of course building an additional assembly/project just to store a single type to reference that assembly in both projects ...is the worst idea I think.

Ridge answered 26/6, 2016 at 19:1 Comment(1)
define an IInterface (or the base class) and put it in a separate DLL, both projects can reference itBolyard
P
44

What is a dependency?

In order to understand what circular dependency is, it is better to understand what is a dependency and what it means to the compiler.

Let's say you have a project and, in a class, you have the following defined:

Public Class MyClass
    'Some code here
    Private MyString As String
    'Some code there
End Class

When compiling your project, the compiler runs into the String class, which is defined in a DLL file called System. It will then link that DLL to your project, so at run-time, when defining or doing operation on the string, the System.dll will be loaded to perform those.

Now, let's say you have, further in your class, the following definition

'Some code here
Private MyObjet as CustomClass1
'Some code there

And let's say CustomClass1 is defined in another project of yours, named Project2.DLL:

Public Class CustomClass1
    'Your custom class code
End Class

So when compiling your first project, the compiler will run into CustomClass1 definition, it knows it lays into Project2.dll and therefore will compile Project2 before, in order to be able to add that reference in your first project.

That's what a dependency is, it's hierarchical, there must be a starting point. Even the String class is dependant on other classes, and at the end, they all rely on bytes or bits to do the job, because that's the only thing a computer can do, play with 1 and 0.

So the circular part

So if you have, in Project2, a reference (a field definition, or something like that) that link to your first project, what happens?

  • The compiler reads your first project, then runs into CustomClass1
  • Then it tries to compile Project2, since CustomClass1 is defined there
  • Then it runs to a class defined in your first project
  • It tries to compile your first project in order to link it to the second
  • Then it runs to CustomClass1
  • Then it tried to compile Project2
  • I guess you got it...

So at some point the compiler displays an error, saying it cannot compile, as it doesn't understand what you're trying to do...

Yes, computers are that stupid.

How to solve it ?

Solving these kind of issue is sometimes difficult, but the basic idea is to build up a hierarchical structure, put the base class (those which don't need dependencies) together, then build up on them.

Take all the classes that depend on each other and put them together, they form a layer for something you try to do in your application.

Pidgin answered 26/6, 2016 at 20:32 Comment(0)
P
40

A circular dependency is where Project A depends on something in Project B and project B depends on something in Project A. This means to compile Project A you must first compile Project B, but you can't do that as B requires A to be compiled. This is the problem that circular dependencies cause.

If you introduce a circular dependency to a project that you've already built it can be hard to spot as the standard build options don't remove the existing object files thus enabling you to build A (or B) first. You'll only spot it when you try on a different machine that's never built the solution before or if you do a clean & build.

re-designing in my case will mean define the same type in both projects, which I don't think that could be good practices neither.

In this case you need to create a third project "C" which contains the classes that both A and B depend on so they no longer depend on each other. You might get away with just splitting the classes up so that dependencies can be sorted that way without creating the third project.

Paperweight answered 26/6, 2016 at 19:7 Comment(4)
Thanks for answer. I seen other answers explaining what is a circular dependency more or less with similar words, but it doesn't explains the reason at all, see, I mean that what is the bad thing about trying to have Project A depending on Project B and viceverse?. Why this cannot be compiled? what is the exact reason of this problem?.Ridge
@Ridge If your question is "Why can't I have a circular dependency?" rather than "What is a circular dependency and how can I solve it?", you might want to edit your question to make that clear.Comeon
@Ridge because, as the name states, circular depedency is circular, so a compiler has no way to tell which project goes first. Philosphically speaking, it would be asking a computer who came first, the egg or the chicken ?Pidgin
@Comeon "What is a circular dependency" implies a necessary explanation of what reason it causes a error/mistake related with the compiler, that explanation was not gave in the answer, but I didn't asked a different question neither unrelated, do you really think it deserves to publish another additional thread to explain a circular dependency?, sure then we can introduce a new modal of QA ...in fascicles. Common, much people like you can find any reason to discuss for every little thing.The worst thing is that something else thinks is a good idea to upvote. SuperPeanut thanks for explain.Ridge
D
2

Easiest way I know to fix CD is to create a PROJECT-of-Interfaces and have the projects that are involved in the CD to reference the PROJECT-of-interfaces, instead of each other. Little messy, but it works.

Disarm answered 12/3, 2021 at 16:57 Comment(0)
C
-4

instead of using projects as references use the builded DLL of that project for referencing.. if you do the same in every modules of solution u can solve it. if u have two projects named as 'main' and 'sub' then in the main project add DLL of Sub project as refrence file and the same time in Sub project add the DLL of main project as reference..

Cid answered 1/10, 2019 at 5:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.