Я пытаюсь распечатать свой список карточек, поэтому ниже я говорю, что давайте просто вернем версию списка карточек ToString()
:
public override string ToString()
{
return Cards.ToString();
}
Поэтому, когда я вызываю ToString()
для списка карточек, он возвращает строковое представление этого списка карточек, и я собираюсь вернуть его из своего ToString()
. Поэтому я пытаюсь создать здесь делегацию.
Поэтому каждый раз, когда я вызываю System.Console.WriteLine(deck);
, он должен вызывать мой ToString()
, и я хочу делегировать печать функции ToString()
, которая принадлежит списку карточек, например так:
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();
}
}
Когда я пытаюсь запустить его, я вижу то, что, как я думал, будет целой кучей экземпляров [Card]
снова и снова, но на самом деле было напечатано System.Collections.Generic.List
1[Card]one time. I don’t know why
System.Collections.Generic.List1
, напечатанное с [Card]
.
Итак, я предполагаю, что я вернул или почти вернул представление этого списка карт, однако, когда я вызвал ToString()
в списке карт, который, в свою очередь, также вызвал ToString()
в моем классе Card, что создает огромную цепочку делегирования с самого начала. вызывается верхний уровень ToString()
, который вызывает карту ToString()
, а та, в свою очередь, также вызывает ToString()
в классе Card
.
Поэтому я решил определить функцию ToString()
в самом классе Card
, и оттуда я могу вернуть строковое представление карт, и это то, что я попытался сделать следующим образом:
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;
}
}
Но это не то, что происходит, я ожидал увидеть что-то вроде [Ace of Diamonds, Two of Diamonds...
и так далее, но вместо этого я продолжаю получать System.Collections.Generic.List
1[Карта]`
Я попытался следовать этой документации для помощи: https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=netframework-4.8
но я обнаружил, что это было немного ошеломляюще в первую неделю изучения C#.
Я также пытался следить за Enigmativity в этом вопросе, но до сих пор не могу понять это.
Вы должны изменить свой метод ToString()
внутри класса Deck
на String.Join()
вместо результатов:
public override string ToString()
{
return "[" + string.Join(", ", Cards.Select(c => c.ToString())) + "]";
}
Что дает следующие результаты:
[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]
Как видно из документации, сигнатура метода выглядит примерно так:
string Join (string separator, IEnumerable<string> values);
Итак, нам нужно передать разделитель строк и коллекцию IEnumerable<string>
. Мы просто указываем ", "
в качестве разделителя и извлекаем ToString()
из каждой строки в коллекции с помощью LINQ, используя Enumerable.Select()
.
List.ToString() не перебирает все элементы в списке, вызывая их метод toString(). Вы должны сделать это сами.
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;
}
}
странно, за ваш ответ я получаю error CS1002: ; expected
за эту закрывающую фигурную скобку на этом foreach
и спасибо, что научили меня выполнять итерации вручную.
странно, измените ваш card.toString()
на card.ToString()
, я уже сделал это на своем конце, и я не знал, что мы можем использовать var
в C#, еще один урок для меня.
+1, потому что ваш код самый быстрый. Я провел несколько тестов и обнаружил, что ваш код в среднем в 1,5-4,5 раза быстрее моего (см. мой ответ). Похоже, что с помощью Linq мы можем значительно уменьшить шум кода, но в любом случае заплатим небольшую цену (незначительную сумму).
Я сделал это с Linq Aggregate
и интерполяция строк
public override string ToString()
{
return $"[{Cards.Select(a => a.ToString()).Aggregate((b, c) => $"{b}, {c}")}]";
}
Вы проверяли это? это похоже на синтаксическую ошибку для меня.
Не могли бы вы опубликовать свою ошибку, пожалуйста.
У вас есть строка в кавычках с кавычками в середине, которые не экранированы - я не верю, что это скомпилируется. У меня нет ошибки - мне не нужно было помещать ее в компилятор.