Печатать значения ArrayList вместо имени класса

Я хотел бы напечатать все десять случайно сгенерированных точек для каждого объекта в ArrayList AL.

public class Point
    {
        public int x;
        public int y;
    
        public Point(int x, int y)
        {
            x = this.x;
            y = this.y;
        }
        
    }    

public class ArrayListTest
    {
        public static void Main(string[] args)
        {
            ArrayList AL = new ArrayList();
            Random Rnd = new Random();
            for (int i = 1; i <= 10; i++)
            {
                Point p = new Point(Rnd.Next(50), Rnd.Next(50));
                AL.Add(p);            
            }
    
        PrintValues(AL);
        }
    
        public static void PrintValues(IEnumerable myList)
        {
            
            foreach (Object obj in myList)
                Console.WriteLine("{0} ", obj);
        }
    }

Вывод на консоль:

Point 
Point 
Point 
Point 
Point 
Point 
Point 
Point 
Point 
Point 

Моя проблема в том, что напечатано имя класса объекта, а не значения объектов. Я использую .NET Framework v4.8.


person DerDave    schedule 21.10.2020    source источник
comment
Прежде всего, не используйте ArrayList, используйте List‹Point›. Во-вторых, переопределите ToString() для печати x и y   -  person insane_developer    schedule 21.10.2020
comment
Покажите нам свой Point класс или подтвердите, что вы используете System.Drawing.Point. Ваш код отлично работает при использовании System.Drawing.Point.   -  person Matthew Watson    schedule 21.10.2020
comment
В качестве альтернативы данным ответам вы можете рассмотреть возможность использования Point Struct вместо собственного класса Point.   -  person Fildor    schedule 21.10.2020
comment
У вас есть назначения X и Y в конструкторе, которые идут в неправильном направлении.   -  person Matthew Watson    schedule 21.10.2020


Ответы (2)


(Кроме того: я рекомендую вам не определять свой собственный класс с именем Point. Он может конфликтовать со встроенным классом и вызывать путаницу. Вы должны дать своему классу другое имя.)

Итак, что происходит, когда вы делаете Console.WriteLine(object obj), так это то, что внутри Console.WriteLine() он вызывает object.ToString(), чтобы определить строку для записи.

По умолчанию, если вы не напишете собственную реализацию ToString(), она вернет имя класса — вот почему вы видите Point в выводе.

Поскольку вы пишете свой собственный класс Point, вы можете переопределить его ToString(), чтобы он возвращал отформатированную строку. Это лучшее решение.

Предполагая, что ваш класс Point имеет значения X и Y, вы можете сделать это, добавив в класс следующее:

public override string ToString()
{
    return $"X={x}, Y={y}";
}

Если вы не хотите этого делать (или предположим, что это сторонний класс, который вы не можете изменить), вам придется явно отформатировать строку, прежде чем передавать ее в Console.WriteLine().

К сожалению, поскольку вы используете ArrayList, вы получите только object, поэтому для его форматирования вам нужно будет привести его к правильному типу, чтобы получить его значения X и Y:

foreach (Object obj in myList)
{
    Point p = (Point)obj;
    Console.WriteLine("X={0}, Y={1}", p.x, p.y);
}

Или вы можете воспользоваться тем фактом, что foreach вместо IEnumerable сделает приведение за вас, если вы объявите переменную цикла как правильный тип:

foreach (Point p in myList)
{
    Console.WriteLine("X={0}, Y={1}", p.x, p.x);
}

Однако гораздо лучше использовать List<Point>, а не ArrayList, тогда элементы будут иметь тип Point:

static class Program
{
    public static void Main(string[] args)
    {
        List<Point> AL  = new List<Point>();
        Random      Rnd = new Random();
        for (int i = 1; i <= 10; i++)
        {
            Point p = new Point(Rnd.Next(50), Rnd.Next(50));
            AL.Add(p);
        }

        PrintValues(AL);
    }

    public static void PrintValues(IEnumerable<Point> myList)
    {
        foreach (var p in myList)
        {
            Console.WriteLine("X={0}, Y={1}", p.x, p.x);
        }
    }
}

И последнее замечание: вы можете рассмотреть возможность использования структуры System.Drawing.Point или System.Windows.Point, а не своего собственного класса Point.

person Matthew Watson    schedule 21.10.2020

Вы не используете общие коллекции, которые были бы здесь более идеальными. Но поскольку это не так, вы работаете с objects. Реализация ToString по умолчанию для объекта вернет имя объекта. Вам нужно будет привести свой объект к типу Point, чтобы работать с ним.

Это один из способов вернуть объект в точку

public static void PrintValues(IEnumerable myList)
{
    
    foreach (var point in myList.Cast<Point>())
        Console.WriteLine($"{obj.X} {obj.Y}");
}
person Jonesopolis    schedule 21.10.2020
comment
Класс @Fildor Point добавлен в вопрос. - person DerDave; 21.10.2020