1.4.27 Fields Whose Type Is Their Own Class

A Class Can Contain a Reference to Another Object of the Same Type

You have already defined fields whose type is another class.

For example:

class Player
{
    public Team team;
}

A class can also contain a field whose type is the same class.

For example:

class Player
{
    public string name;
    public Player teammate;
}

The teammate field can refer to another Player object.

Read the Field Declaration Carefully

In:

public Player teammate;

the field type is:

Player

The field name is:

teammate

Read it as:

The Field Does Not Mean the Object Contains a Full Duplicate Player

Suppose:

Player player1 = new Player();
Player player2 = new Player();

Then:

player1.teammate = player2;

connects player1 to the existing player2 object.

Conceptually:

player1 : Player
      |
      | teammate
      v
player2 : Player

The assignment stores an object reference.

It does not copy all of player2 into player1.

The Field Begins Like Other Reference Fields

If no Player has been assigned yet, the field may contain:

null

For a newly created Player:

Player player1 = new Player();

the state may include:

teammate = null

until the relationship is assigned.

Assign Another Object of the Same Class

After creating two Player objects:

Player player1 = new Player();
Player player2 = new Player();

you can connect them:

player1.teammate = player2;

Now:

player1.teammate

reaches a Player object.

Nested access can continue from there:

player1.teammate.name

when the reference is not null.

The Two Objects Still Have Separate State

Suppose:

player1.name = "Jordan";
player2.name = "Casey";
player1.teammate = player2;

Then:

player1.name              = "Jordan"
player1.teammate.name     = "Casey"

The relationship does not merge the two Player objects.

Each keeps its own fields and identity.

Self-Typed Fields Can Model Relationships Between Similar Things

In a soccer context, the same class might represent:

  • a player's teammate;
  • a team's rival team;
  • a match's next match.

For example:

class Team
{
    public string name;
    public Team rival;
}

The usefulness depends on the domain model.

Do not add a self-typed field merely because the syntax is available.

The relationship should come from the current design.

Avoid Accidentally Pointing an Object to Itself

C# can technically allow a reference such as:

player1.teammate = player1;

But whether that relationship makes sense depends on the model.

For a teammate relationship, it would usually not represent the intended soccer meaning.

Use the requirement and UML to determine which object the field should reference.

Connect the Field to UML

A class diagram might show:

Player
-------------------------
name : string
teammate : Player

An object diagram might show:

player1 : Player -------- player2 : Player

The C# field:

public Player teammate;

makes the same-type relationship possible.

The runtime assignment:

player1.teammate = player2;

establishes the relationship between the specific objects.

The Main Idea

A custom class type can appear as a field type even inside its own class.

That allows an object to refer to another object of the same kind:

Activity diagram showing Player Player, then Team Team.
PlayerPlayer.
  • New
  • Changed
  • Removed

The field represents a relationship, not a duplicate copy of the object.