Consider:
team1.ShowTeam();
The ShowTeam method contains:
public void ShowTeam()
{
this.DisplayName();
}
Then DisplayName contains:
public void DisplayName()
{
System.Console.WriteLine(this.name);
}
Execution does not stay on one source line.
It moves through a sequence of method calls.
Start with:
team1.ShowTeam();
The first receiver is:
team1
The first method is:
ShowTeam()
Now move into the method body.
Inside ShowTeam, the program reaches:
this.DisplayName();
Because this is still team1, the second call is:
team1.DisplayName()
The nested call path is:
caller
↓
team1.ShowTeam()
↓
team1.DisplayName()
↓
Console.WriteLine(...)
Each new method call temporarily moves execution into another method.
When the called method finishes, execution returns to the statement after the call in the previous method.
Conceptually, while DisplayName() is running:
DisplayName() ← current method
ShowTeam() ← waiting for DisplayName to finish
original caller ← waiting for ShowTeam to finish
When DisplayName() finishes, it leaves the active call chain.
Execution returns to ShowTeam().
When ShowTeam() finishes, execution returns to its caller.
The Visual Studio Call Stack makes this structure visible in CO-037.
Now consider an object-to-object call:
player1.ShowTeamName();
Inside:
public void ShowTeamName()
{
this.team.DisplayName();
}
The call chain includes different current objects:
player1.ShowTeamName()
↓
team1.DisplayName()
Inside ShowTeamName, this refers to player1.
Inside DisplayName, this refers to team1.
Tracing requires both:
A small trace can be organized as:
| Step | Current object | Current method | Next call |
|---|---|---|---|
| 1 | player1 |
ShowTeamName() |
team1.DisplayName() |
| 2 | team1 |
DisplayName() |
display statement |
| 3 | team1 |
DisplayName() finishes |
return to Player method |
| 4 | player1 |
ShowTeamName() finishes |
return to caller |
This helps prevent the common mistake of assuming this always refers to the same object through the entire call chain.
A conceptual sequence diagram may show:
caller player1 : Player team1 : Team
| | |
| ShowTeamName() |
|------------->| |
| | DisplayName() |
| |------------------->|
| | |
The vertical order shows call order.
The horizontal direction shows which object receives each message.
Every method in the current examples is void.
Methods still finish and return execution to their caller.
They simply do not return a data value.
Methods that return values are taught later.
A weak trace might say:
The program displays Wildcats.
That may be the visible result, but it hides how execution reached that result.
A stronger trace explains:
The caller invokes
ShowTeamName()onplayer1. That method follows the Player's Team reference and callsDisplayName()onteam1. The Team method displays its name, then execution returns to the Player method and finally to the original caller.
That explanation connects source structure to runtime flow.
At every method call, ask:
this refer to inside that method?Those questions prepare you to use debugger stepping and the Call Stack in CO-037.