0

I am trying to get my list of cards printing and so below I am saying let's just return the cards list version of ToString():

  public override string ToString()
  {
      return Cards.ToString();
  }

So when I call ToString() on a list of cards, it will return a string representation of that list of cards and I am going to return that from my ToString(). So I am trying to set up delegation here.

So anytime I call System.Console.WriteLine(deck); it should call my ToString() and I want to delegate printing to the ToString() function that belongs to the list of cards like so:

using System;
using System.Collections.Generic;

class Program
{
    public static void Main()
    {
        Deck deck = new Deck();
        System.Console.WriteLine(deck);
    }
}

public class Deck {
   public List<Card> Cards = new List<Card>();

public Deck() {
  string[] ranks = { "Ace", "Two", "Three", "Four", "Five" };
  string[] suits = { "Diamonds", "Hearts", "Clubs", "Spades" };

  foreach (string suit in suits) {
      foreach (string rank in ranks) {
          Card card = new Card(rank, suit);
          Cards.Add(card);
      }
  }
}
  
  public override string ToString()
  {
      return Cards.ToString();
  }
}

When I try running it, I see what I thought would be a whole bunch of instances of [Card] over and over again, but what actually got printed out was System.Collections.Generic.List1[Card]one time. I don’t know whySystem.Collections.Generic.List1 printed out with [Card].

So my guess is that I returned or almost returned a representation of that list of cards, however, when I called ToString() on the list of cards that in turn called ToString() on my Card class as well which creates a huge chain of delegation from the very top level ToString() gets called and that calls the card ToString() and that in turn calls ToString() on the Card class as well.

So I thought I would define a ToString() function on the Card class itself and from there I can return a string representation of the cards and that's what I attempted to do like so:

using System;
using System.Collections.Generic;

class Program
{
    public static void Main()
    {
        Deck deck = new Deck();
        System.Console.WriteLine(deck);
    }
}

public class Deck {
   public List<Card> Cards = new List<Card>();

public Deck() {
  string[] ranks = { "Ace", "Two", "Three", "Four", "Five" };
  string[] suits = { "Diamonds", "Hearts", "Clubs", "Spades" };

  foreach (string suit in suits) {
      foreach (string rank in ranks) {
          Card card = new Card(rank, suit);
          Cards.Add(card);
      }
  }
}
  
  public override string ToString()
  {
      return Cards.ToString();
  }
}

public class Card {
    // properties
    public string suit { get; set; }
    public string rank { get; set; }
    
    public override string ToString()
    {
      return $"{rank} of {suit}"; 
    }

    public Card(string rank, string suit){
       //initializations
       this.rank = rank;
       this.suit = suit;
    }
    
} 

But that's not what happens, I expected to see printed up something like [Ace of Diamonds, Two of Diamonds... and so on, but instead I continue to get System.Collections.Generic.List1[Card]`

I attempted to follow this documentation for assistance: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=netframework-4.8

but I found it to be a bit overwhelming on my first week of C#.

I also tried to follow Enigmativity in this question but I am still unable to figure this out.

halfer
  • 19,824
  • 17
  • 99
  • 186
Daniel
  • 14,004
  • 16
  • 96
  • 156

3 Answers3

3

You should change your ToString() method inside the Deck class to String.Join() the results instead:

public override string ToString()
{
    return "[" + string.Join(", ", Cards.Select(c => c.ToString())) + "]";
}

Which gives the following results:

[Ace of Diamonds, Two of Diamonds, Three of Diamonds, Four of Diamonds, Five of Diamonds, Ace of Hearts, Two of Hearts, Three of Hearts, Four of Hearts, Five of Hearts, Ace of Clubs, Two of Clubs, Three of Clubs, Four of Clubs, Five of Clubs, Ace of Spades, Two of Spades, Three of Spades, Four of Spades, Five of Spades]

As seen in the docs, the method signature looks something like the following:

string Join (string separator, IEnumerable<string> values);

So we need to pass a string delimiter and a IEnumerable<string> collection. We simply give ", " as the delimiter and we extract the ToString() from each string in the collection with LINQ using Enumerable.Select()

RoadRunner
  • 25,803
  • 6
  • 42
  • 75
1

I did it with Linq Aggregate and string interpolation

    public override string ToString()
    {
        return $"[{Cards.Select(a => a.ToString()).Aggregate((b, c) => $"{b}, {c}")}]";
    }
DotNet Developer
  • 2,973
  • 1
  • 15
  • 24
0

List.ToString() does not iterate over all the elements in the list, calling their toString() method. You have to do that yourself.

public Deck() {
  string[] ranks = { "Ace", "Two", "Three", "Four", "Five" };
  string[] suits = { "Diamonds", "Hearts", "Clubs", "Spades" };

  foreach (string suit in suits) {
      foreach (string rank in ranks) {
          Card card = new Card(rank, suit);
          Cards.Add(card);
      }
  }
}

  public override string ToString()
  {
      string s = "[";
      foreach (var card in Cards) {
        s += card.ToString() + ",";
      }
      s += "]";
      return s;
  }
}
weirdev
  • 1,388
  • 8
  • 20
  • weirdev, for your answer I am getting `error CS1002: ; expected` for that closing curly brace on that `foreach` and thank you for teaching me that I have to manually iterate. – Daniel Jun 14 '19 at 04:21
  • 1
    weirdev, change your `card.toString()` to `card.ToString()`, I already did on my end and I did not know we could use `var` in C#, another lesson for me. – Daniel Jun 14 '19 at 04:26
  • +1, because your code is the fastest. I did some tests and revealed that your code is, at the average, 1.5-4.5 times faster than mine (see my answer). Looks like with Linq we can significantly reduce code noise but pay a little cost (negligible amount) anyway. – DotNet Developer Jun 18 '19 at 09:29