c# переопределение ToString() для коллекции

252
06 июля 2018, 04:30

Как можно переопределить метод ToString() для коллекции?

List<Place> spisok = new List<Place>();
for (int i = 0; i < 20; i++)
     spisok.Add(new Place(PlaceStatus.Free));

Я хочу при вызове spisok.ToString() я получал String формата 0,0,0,0 (т.е. элементы через запятую)

Или для такой коллекции аналогично

var spisok = new Place[20];
for (int i = 0; i < 20; i++)
     spisok[i] = new Place(PlaceStatus.Free));

Ниже код используемых элементов. В классе попытался перегрузить метод ToString(), он выдает числовые значения, когда объект 1. Но в случае с массивом, это текст - запись о классе

    public enum PlaceStatus
    {
        Free,
        Booked,
        Paid,
        Confirmed
    }
    public class Place
    {
        public PlaceStatus Status { get; set; }
        public Place(PlaceStatus status)
        {
            Status = status;
        }
        public override string ToString()
        {
            return ((int)Status).ToString();
        }
    }
Answer 1

Создайте статический класс-helper. Это будет выглядеть примерно так:

public static class PlaceCollectionHelper
{
    public static string ToString(this IEnumerable<Place> Collection, string Separator)
    {
        return string.Join(Separator, Collection);
    }
}

И далее используйте в своём коде:

string spisokStr = spisok.ToString(",");

UPD:
Предыдущий вариант является расширением, так как явно переопределить ToString() у существующей коллекции нельзя. Однако если Вам необходимо, чтобы сторонние методы могли вызывать нужное Вам преобразование Вашей коллекции в строку, придется создавать новый тип, который будет наследоваться от типа нужной Вам коллекции. Здесь есть 2 пути. Давайте рассмотрим их.

0) Самым лаконичным решением будет то, которое представлено в соседнем ответе:

public class PlaceCollection : List<Place>
{
    public override string ToString()
    {
        return string.Join(", ", this);
    }
    public string ToString(string Separator)
    {
        return string.Join(Separator, this);
    }
}

Вы просто создаете класс, который наследуется от листа с нужным Вам типом, где и переопределяете ToString() нужным Вам образом. Как Вы понимаете, работает эта конструкция точно так же, как и обычный лист:

PlaceCollection collection = new PlaceCollection { new Place(PlaceStatus.Free), new Place(PlaceStatus.Booked) };
collection.Add(new Place(PlaceStatus.Paid));

Однако теперь, если Вы вызовете, скажем, Console.WriteLine, которая при передачи в нее объекта автоматически вызывает у него ToString(), то получите уже:

Console.WriteLine(collection);
// 0, 1, 2

1) Предыдущий вариант подойдет Вам лишь в том случае, если в качестве коллекции Вы используете List. Однако в Вашем втором примере ясно видно, что Вы так же используете и массив для своих целей. Так что в решении Вашей задаче нам поможет наследование от generic-интерфейса IEnumerable<T>:

public class PlaceCollection : IEnumerable<Place>
{
    #region Var
    private IEnumerable<Place> Collection { get; set; }
    #endregion
    #region Init
    public PlaceCollection(IEnumerable<Place> Collection)
    {
        this.Collection = Collection;
    }
    public static implicit operator PlaceCollection(List<Place> Collection)
    {
        return new PlaceCollection(Collection);
    }
    public static implicit operator PlaceCollection(Place[] Collection)
    {
        return new PlaceCollection(Collection);
    }
    #endregion
    #region Functions
    public IEnumerator<Place> GetEnumerator()
    {
        return Collection.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return Collection.GetEnumerator();
    }
    public override string ToString()
    {
        return string.Join(", ", Collection);
    }
    public string ToString(string Separator)
    {
        return string.Join(Separator, Collection);
    }
    #endregion
}

Доступ к элементам можно производить при помощи Linq, либо же дописать свои индексаторы. В данном классе реализовано неявное приведение, так что Вы вполне можете сделать так:

Place[] placeArray = new Place[] { new Place(PlaceStatus.Free), new Place(PlaceStatus.Booked) };
PlaceCollection collection = placeArray;

Или так:

List<Place> placeList = new List<Place> { new Place(PlaceStatus.Free), new Place(PlaceStatus.Booked) };
PlaceCollection collection = placeList;

Однако результат все равно будет один:

Console.WriteLine(collection);
// 0, 1

И так как наследовались мы от IEnumerable<Place>, то Вам доступно получение энумератора:

foreach (Place p in collection)
    Console.WriteLine(p);
// 0
// 1

Выбирайте наиболее удобный Вам метод и удачи в Ваших решениях)

Answer 2
public class MyTypeList : List<MyClass>
{
    public override string ToString()
    {
        return ...
    }
}
READ ALSO
C#. Создание сводной диаграммы через epplus

C#. Создание сводной диаграммы через epplus

Нужна помощь с преобразованием таблицы в сводную диаграмму, таблица формируется из datagridview в excel через epplus, на скринах пример таблицы и сводной...

169
При конвертации в String - вывод &ldquo;не число&rdquo;

При конвертации в String - вывод “не число”

Есть цикл, в котором генерируется NewTimeРешил проверить, какое число там получается, поставил MessageBox, и на выводе показывает что NewTime - "не число"

135
Создание окна с текстом в библиотеке классов c#

Создание окна с текстом в библиотеке классов c#

У меня есть библиотека классов, мне нужно создать окно, которое будет постоянно показыватьсяТам должно быть многострочное поле с текстом,...

143