Circular references are not always harmful - there are some use cases where they can be quite useful. Doubly-linked lists, graph models, and computer language grammars come to mind. However, as a general practice, there are several reasons why you may want to avoid circular references between objects.
Data and graph consistency. Updating objects with circular references can create challenges in ensuring that at all points in time the relationships between objects are valid. This type of problem often arises in object-relational modeling implementations, where it's not uncommon to find bidirectional, circular references between entities.
Ensuring atomic operations. Ensuring that changes to both objects in a circular reference are atomic can become complicated - particularly when multithreading is involved. Ensuring consistency of an object graph that is accessible from multiple threads requires special synchronization structures and locking operations to ensure that no thread sees an incomplete set of changes.
Physical separation challenges. If two different classes A and B reference each other in a circular fashion, it can become challenging to separate these classes into independent assemblies. It's certainly possible to create a third assembly with interfaces IA and IB that A and B implement; allowing each to reference the other through those interfaces. It's also possible to use weakly typed references (e.g. object) as a way to break the circular dependency, but then access to the method and properties of such an object couldn't be easily accessed - which can defeat the purpose of having a reference.
Enforcing immutable circular references. Languages like C# and VB provide keywords to allow references within an object to be immutable (readonly). Immutable references allow a program to ensure that a reference refers to the same object for the lifetime of the object. Unfortunately, it's not easy to use the compiler-enforced immutability mechanism to ensure that circular references cannot be changes. It can only be done if one object instantiates the other (see C# example below).
class A
{
private readonly B m_B;
public A( B other ) { m_B = other; }
}
class B
{
private readonly A m_A;
public A() { m_A = new A( this ); }
}
Program readibility and maintainability. Circular references are inherently fragile and easy to break. This stems partly from the fact that reading and understanding code that includes circular references is harder than code that avoids them. Ensuring that your code is easy to understand and maintain helps to avoid bugs and allows changes to be made more easily and safely. Objects with circular references are more difficult to unit test because they cannot be tested in isolation from one another.
Object lifetime management. While .NET's garbage collector is capable of identifying and dealing with circular references (and correctly disposing such objects), not all languages/environments can. In environments that use reference counting for their garbage collection scheme (e.g. VB6, Objective-C, some C++ libraries) it is possible for circular references to result in memory leaks. Since each object holds on to the other, their reference counts will never reach zero, and hence will never become candidates for collection and cleanup.