#c_sharp #коллекции #переопределение
Как можно переопределить метод ToString() для коллекции?
List spisok = new List();
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();
}
}
Ответы
Ответ 1
Создайте статический класс-helper. Это будет выглядеть примерно так:
public static class PlaceCollectionHelper
{
public static string ToString(this IEnumerable Collection, string Separator)
{
return string.Join(Separator, Collection);
}
}
И далее используйте в своём коде:
string spisokStr = spisok.ToString(",");
UPD:
Предыдущий вариант является расширением, так как явно переопределить ToString() у
существующей коллекции нельзя. Однако если Вам необходимо, чтобы сторонние методы могли
вызывать нужное Вам преобразование Вашей коллекции в строку, придется создавать новый
тип, который будет наследоваться от типа нужной Вам коллекции. Здесь есть 2 пути. Давайте
рассмотрим их.
0) Самым лаконичным решением будет то, которое представлено в соседнем ответе:
public class PlaceCollection : List
{
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:
public class PlaceCollection : IEnumerable
{
#region Var
private IEnumerable Collection { get; set; }
#endregion
#region Init
public PlaceCollection(IEnumerable Collection)
{
this.Collection = Collection;
}
public static implicit operator PlaceCollection(List Collection)
{
return new PlaceCollection(Collection);
}
public static implicit operator PlaceCollection(Place[] Collection)
{
return new PlaceCollection(Collection);
}
#endregion
#region Functions
public IEnumerator 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 placeList = new List { new Place(PlaceStatus.Free), new Place(PlaceStatus.Booked) };
PlaceCollection collection = placeList;
Однако результат все равно будет один:
Console.WriteLine(collection);
// 0, 1
И так как наследовались мы от IEnumerable, то Вам доступно получение энумератора:
foreach (Place p in collection)
Console.WriteLine(p);
// 0
// 1
Выбирайте наиболее удобный Вам метод и удачи в Ваших решениях)
Ответ 2
public class MyTypeList : List
{
public override string ToString()
{
return ...
}
}