Answered Need help with syntax of lists in an initialized object

bondra

Well-known member
Joined
Oct 24, 2020
Messages
77
Programming Experience
Beginner
This is probably a no brainer but I just can't get my head around this. I've created a class and a field of a List<T>.
But is stuck on how to type the correct syntax for the specific List<T> upon creation of an object.

So, what should go after the comma in my screenshot where the overload tipsy is displayed? :)

hlp.jpg
 
Last edited by a moderator:
Solution
As for the question, there's a lot to fix there. Firstly, if you're going to use auto-properties then you don't define your own backing fields because the auto-property does that for you. In the old days, we used to have to implement a property like this:
C#:
public class Player
{
    private string _name;
  
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name = value
        }
    }
}
Nowadays, if all you do in the getter and setter is get and set the backing field, you can achieve the same result with this:
C#:
public class Player
{
    public string Name { get; set; }
}
The system will implement the getter, the setter and the backing field behind the...
First things first, don't post pictures of code. They are hard to read on a phone and you can't copy and paste the code if you want to test it or show a modified version. I do want to show you a modified version of your code but now I have to type it out from scratch instead of copying what you already have and modifying it.
 
As for the question, there's a lot to fix there. Firstly, if you're going to use auto-properties then you don't define your own backing fields because the auto-property does that for you. In the old days, we used to have to implement a property like this:
C#:
public class Player
{
    private string _name;
  
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name = value
        }
    }
}
Nowadays, if all you do in the getter and setter is get and set the backing field, you can achieve the same result with this:
C#:
public class Player
{
    public string Name { get; set; }
}
The system will implement the getter, the setter and the backing field behind the scenes. If you look at the private members of the type, you'll find that you can actually access the implicitly declared field named _Name.

In the case of collection properties, you should pretty much always declare then as read-only and create the collection internally. What that means is that calling code can get the existing collection and then get, set, add and remove items but the existing collection cannot be replaced in its entirety:
C#:
public class Player
{
    public string Name { get; set; }
    public List<int> Turns { get; } = new List<int>();
}
That's how it is throughout the .NET Framework already, with properties like Control.Controls, ComboBox.Items, DataTable.Rows, etc, etc.

What that means in your scenario is that, if you're not actually going to adding any turns in the collection, you don't need to care about that property in the constructor:
C#:
public class Player
{
    public string Name { get; set; }
    public bool PlayerIsComputer { get; set; }
    public int RoundsPlayed { get; set; }
    public List<int> Turns { get; } = new List<int>();

    public Player(string name, bool playerIsComputer, int roundsPlayed)
    {
        Name = name;
        PlayerIsComputer = playerIsComputer;
        RoundsPlayed = roundsPlayed;
    }
}
To be frank, I'm not sure why you would need the roundsPlayed parameter either. Won't that always be zero for a new Player? If so, there's no point using a parameter and you can just set the property explicitly to zero.

If there was a reason to pass in some existing values for Turns then you could do it like this:
C#:
public class Player
{
    public string Name { get; set; }
    public bool PlayerIsComputer { get; set; }
    public int RoundsPlayed { get; set; }
    public List<int> Turns { get; } = new List<int>();

    public Player(string name, bool playerIsComputer, int roundsPlayed)
    {
        Name = name;
        PlayerIsComputer = playerIsComputer;
        RoundsPlayed = roundsPlayed;
    }

    public Player(string name, bool playerIsComputer, int roundsPlayed, IEnumerable<int> turns)
        : this(name, playerIsComputer, roundsPlayed)
    {
        Turns.AddRange(turns);
    }
}
In that case, the second constructor invokes the first constructor to do the same thing with the first three parameters, then adds the turns values to the existing collection. You could then create a new Player like this:
C#:
players.Add(new Player(ShuffleName(), true, 0));
or like this:
C#:
players.Add(new Player(ShuffleName(), true, 0, new [] {1, 2, 3}));
Because the turns parameter is type IEnumerable<int>, you can pass any type that implements that interface, which includes a List<int> or an int array or many other less common options.
 
Last edited:
Solution
To answer the question as asked, if you were going to use the code you had originally (which you absolutely should not) then it would look like this:
C#:
players.Add(new Player(SuffleName(), true, 0, new List<int>()));
 
Thank you so much for taking your time! Much appreciated!

Turns are supposed to store points for a player for each round. So yes I guess I can get rid of the roundsPlayed field and get the count by looping the turns list.
I'm currently studying C# on a quite basic level where we now have reached OOP. From a beginners point of view to get the basics. Is your solution using IEnumerable the best to understand the fundamentals? IEnumerables is not something we have touched so far at least.

Thanks! :)
 
Last edited:
What potential way would you suggest for this scenario?
Say, for a player object I want to keep track of played rounds and points for each round (where 1 round = 3 attempts of throwing dart). Something like:
- Round 1
- - 23
-- 14
-- 10
- Round 2
-- 10
-- 5
-- 1

What's the best way to store this? Using multiple list? One that holds rounds and one that is "nested" in that parenting list holding the points?

This is how I initially made my class diagram (hope this ones ok to have as a picture):
Capture.PNG
 
Last edited:
Turns are supposed to store points for a player for each round. So yes I guess I can get rid of the roundsPlayed field and get the count by looping the turns list.
I was just suggesting that there was no need for a parameter in the constructor, because that property would be initialised to zero every time. It's not such a bad idea to have a dedicated property for that but you should have a single source of truth. As it stands, it would be possible for the Turns collection to have a number of items that does not match the RoundsPlayed property. A better option would be to implement RoundsPlayed like this:
C#:
public int RoundsPlayed
{
    get
    {
        return Turns.Count;
    }
}
Now you have a dedicated property, making it clear and easy for the calling code, but you know that it will always be in sync with other data.
I'm currently studying C# on a quite basic level where we now have reached OOP. From a beginners point of view to get the basics. Is your solution using IEnumerable the best to understand the fundamentals? IEnumerables is not something we have touched so far at least.
I guess it depends exactly what you consider to be the fundamentals. IEnumerable<T> is an interface and implementing interfaces is an important part of OOP, although probably a level or two up from basic. Essentially, any IEnumerable is a list that you can enumerate using a foreach loop and an IEnumerable<T> is a strongly-type version of that. In this case, the idea is that you can pass any enumerable list as an argument. You could declare that parameter as int[] or List<int> but then you are limited to passing in only one type of object when the actual functionality of the constructor doesn't require that type. If you want to stick with types that you've already covered though, by all means use one of those types.

That said, this is probably a moot point because, as I said, a new player probably has no turns at the outset anyway so you should never need to pass anything in there.
 
Last edited:
What potential way would you suggest for this scenario?
Say, for a player object I want to keep track of played rounds and points for each round (where 1 round = 3 attempts of throwing dart). Something like:
- Round 1
- - 23
-- 14
-- 10
- Round 2
-- 10
-- 5
-- 1

What's the best way to store this? Using multiple list? One that holds rounds and one that is "nested" in that parenting list holding the points?

This is how I initially made my class diagram (hope this ones ok to have as a picture):
View attachment 1152
You might define a Round class that had a property each for the three attempts and then a property for the sum of those scores. Your Player class could then have a Rounds property that was a List<Round>. You might even have a TotalScore property that was implemented as a sum of the scores for all rounds.
 
You might define a Round class that had a property each for the three attempts and then a property for the sum of those scores. Your Player class could then have a Rounds property that was a List<Round>. You might even have a TotalScore property that was implemented as a sum of the scores for all rounds.
I agree with having a round class with three properties to hold the values of each round. @jmcilhinney is reading my mind, but is way ahead of me on the thinking part... This is rather close to the way @jmcilhinney was recommending, hopefully its alright, after all. What type of pseudo code can you expect from a man at 04:30 in the morning :) :
C#:
        public class Game
        {
            public Player AddPlayer(Player player)
            {
                return player;
            }
            public Player RemovePlayer(Player player)
            {
                return player;
            }
            public Player CreateAIPlayer(Player player)
            {
                return player;
            }
            public void BeginGame()
            {

            }
        }
        public class Player
        {
            public Player(int roundsPlayed, string playerName, double playerScore, RoundScores roundScores, bool playerIsAI)
            {
                RoundsPlayed = roundsPlayed;
                PlayerName = playerName;
                PlayerScore = playerScore;
                RoundScores = roundScores;
                PlayerIsAI = playerIsAI;
            }
            public int RoundsPlayed { get; set; }
            public string PlayerName { get; set; }
            public double PlayerScore { get; set; }
            public RoundScores RoundScores { get; set; }
            public bool PlayerIsAI { get; set; }
        }
        public class Score
        {
            public Score(double totalScore)
            {
                TotalScore = totalScore;
            }
            public double GetTotalScore(RoundScores roundScores)
            {
                TotalScore = roundScores.Round1Score + roundScores.Round2Score + roundScores.Round3Score;
                return TotalScore;
            }
            public List<Score> ScoresList = new List<Score>();
            public double TotalScore { get; set; }
        }
        public class RoundScores
        {
            public double Round1Score { get; set; }
            public double Round2Score { get; set; }
            public double Round3Score { get; set; }
        }
 
Ask any question if there is something you don't understand. We are after all here to try to help and guide you best we can. One thing however, since I wrote this at 04:30 this morning :
C#:
public class Score { public Score(double totalScore) { TotalScore = totalScore; }
public double GetTotalScore(RoundScores roundScores)
{
TotalScore = roundScores.Round1Score + roundScores.Round2Score + roundScores.Round3Score; return TotalScore;
}
public List<Score> ScoresList = new List<Score>();
public double TotalScore { get; set; } }
That GetTotalScore doesn't really belong there. Whenever you use a class that's designed for holding data, you are best to use that class for only that purpose. Instead, dump any methods you have into another separate class, or even some type of static helper to hold your methods. It not only makes for cleaner code; for it also helps keep to the single responsibility rule for your class structure. So an error on my part for whipping that in there.
 
I've played around and making small progress.
I wonder though, how can the structure in the circle below be achieved? At least for me it looks more structured. Don't know about the best practices collecting it this way. Seems like some sort of nested lists? What's your thoughts on this?

EDIT: Count = 41 is wrong. But you get the idea of the structure :)

Untitled-2.jpg
 
Everything for that has already been covered.
C#:
using System.Collections.Generic;

namespace ConsoleApp1
{
    public class Program
    {
        public static void Main()
        {
            var p = new Player();
            var r = new Round();

            r.FirstAttempt = 16;
            r.SecondAttempt = 5;
            r.ThirdAttempt = 20;

            p.RoundsPlayed.Add(r);
        }
    }

    public class Player
    {
        public List<Round> RoundsPlayed { get; } = new List<Round>();
    }

    public class Round
    {
        public int FirstAttempt { get; set; }
        public int SecondAttempt { get; set; }
        public int ThirdAttempt { get; set; }
    }
}
 
Thanks a lot! So simple and clean!
To play around beforehand with my own solutions, really help me to better understand what I'm trying to achieve. Which also makes it easier to finally grasp your suggestions :)
 
Back
Top Bottom