
Putting it all together
Now, let's have a look how we use the classes to create the Cricket Score Tracker app. The buttons below the Batters section and Bowler section are used to select batsmen and a bowler for the specific over.
While each button is taken care of by its own click event, they all call the exact same method. We will have a look at how that is accomplished in a moment:

Clicking on either button under the Batsmen section will display a modal dialog with a drop-down list populated with the batsmen in the team:

Similarly, when we click on the Select Bowler button, we will see the exact same modal dialog screen displayed. This time, however, it will be a list of bowlers displayed for selection:

Selecting players from the drop-down lists will populate the text on the button clicked with that player's name. This then sets up the current over with the players involved.
Each player will be either a batsman or a bowler (AllRounder class):

So how did we manage to make a single method return two different players? I used a method called GeneratePlayerList(). This method is responsible for creating the player list in the modal dialog that pops up. That is all that method is responsible for. In other words, it performs no other function apart from generating the player list.
Let's look at how the Default.aspx.cs file is created. For simplicity's sake, I just created two lists for each team. I also created an enum for the player selection. The code looks as follows:
public enum SelectedPlayer { Batsman1 = 1, Batsman2 = 2, Bowler = 3 } List<Player> southAfrica; List<Player> india;
In reality, however, you would probably make the list names team1 and team2, and allow the user to select the teams from a setup screen for this game. I have not added this functionality as I am merely trying to illustrate the concepts of OOP here.
In Page_Load, I then populate the lists with players, as follows:
protected void Page_Load(object sender, EventArgs e) { southAfrica = Get_SA_Players(); india = Get_India_Players(); }
Again, for simplicity, I have hard-coded the player names and manually added them to the lists.
In reality, you would probably read this from a database of teams and players. So instead of Get_SA_Players() and Get_India_Players(), you would have a single Get_Players() method that would be responsible for reading the players into the lists.
For now, looking at the Get_SA_Players() method, we simply do the following:
private List<Player> Get_SA_Players() { List<Player> players = new List<Player>(); #region Batsmen Batsman b1 = new Batsman(); b1.FirstName = "Faf"; b1.LastName = "du Plessis"; b1.Age = 33; players.Add(b1); // Rest omitted for brevity #endregion #region All Rounders AllRounder ar1 = new AllRounder(); ar1.FirstName = "Farhaan"; ar1.LastName = "Behardien"; ar1.Age = 33; players.Add(ar1); // Rest omitted for brevity #endregion return players; }
Notice now that the players list is of type List<Player>, and that we are adding Batsman and AllRounder types to it. This is what the term polymorphism means. Remember that one of the aspects of polymorphism we mentioned earlier was:
Therefore, because Batsman and AllRounder inherit from the Player abstract class, they are treated as objects of Player for the List<Player>.
Moving back to the logic to select the batsman or bowler, we look to a method to generate the player list called GeneratePlayerList():
private void GeneratePlayerList(List<Player> team, Type type) { List<string> players = new List<string>(); if (type == typeof(Batsman)) players = (from r in team.OfType<Batsman>() select $"{r.FirstName} {r.LastName}").ToList(); if (type == typeof(AllRounder)) players = (from r in team.OfType<AllRounder>() select $"{r.FirstName} {r.LastName}").ToList(); int liVal = 0; if (ddlPlayersSelect.Items.Count > 0) ddlPlayersSelect.Items.Clear(); foreach (string player in players) { ListItem li = new ListItem(); li.Text = player.ToString(); li.Value = liVal.ToString(); ddlPlayersSelect.Items.Add(li); liVal += 1; } }
You will notice that the method takes a List<Player> argument as well as a Type. The method checks whether type is a Batsman or AllRounder and based on that, reads the first and last names of the players in the list.
The actual aim is to try and write the least amount of code for the maximum required effect. As a rule of thumb, some developers maintain that if a method's length is longer than the code page you are looking at in the IDE, you need to do some refactoring.
Having less code and smaller methods allows the code to be easier to read and understand. It also allows better maintainability of that code because smaller sections of code are easier to debug. In fact, you might experience fewer bugs because you are writing smaller, more manageable pieces of code.
Many years ago, I was part of a team that worked on a project for a large corporation in Cape Town. They had a systems architect called Uthmaan Hendrix. I will never forget this guy. He was the humblest bloke I had ever come across. The documentation he created for the system we worked on was simply incredible. It took almost all the think work out of the code we had to write. The developers didn't have to decide how to architect the project at all.
This project implemented SOLID principles, and understanding the code was really easy. I still have a copy of that document. I still refer to it from time to time. Unfortunately, not all developers have the luxury of having a dedicated systems architect on the project they are working with. It is, however, good for developers to understand what the SOLID design principles are.