-1

Этот код описывает человека и систему создания ID.

class Program
    {
        static void Main()
        {
            Person person1 = new Person("Николай", 19);
            Person person2 = new Person("Андрей", 25);
            Person person3 = new Person("Сергей", 23);
        Console.WriteLine("------------------------------");
        person1.PrintInfo();
        Console.WriteLine("------------------------------");
        person2.PrintInfo();
        Console.WriteLine("------------------------------");
        person3.PrintInfo();
        Console.WriteLine("------------------------------");

        //Поиск по известному ID и вывод информации
        Person.SearchByID(person2.ID).PrintInfo();

        Console.WriteLine("------------------------------");

        //Поиск по случайному ID (Несуществующему)
        Person.SearchByID("25462");
    }
}

public class Person : ID { static List<Person> persons = new List<Person>(); //Список созданных людей

    private string name;
    private int age;
    readonly public string ID;

    public string Name { get { return name; } set { name = value; } }
    public int Age { get { return age; } set { age = value; } }

    public Person(string name = &quot;Неизвестно&quot;, int age = 18)
    {
        ID = CreateID(); //Случайная генерация ID (ID не может повторяться)
        Name = name;
        Age = age;
        Console.WriteLine($&quot;Человек {name} создан&quot;);

        persons.Add(this);
    }

    public void PrintInfo()
    {
        Console.WriteLine($&quot;Имя: {name}\nВозраст: {age}\nID: {ID}&quot;);
    }

    public static Person SearchByID(string id)
    {
        Console.WriteLine($&quot;Поиск пользователя по ID {id}&quot;);
        for (int i = 0; i &lt; persons.Count; i++)
        {
            if (persons[i].ID == id)
            {
                Console.WriteLine(&quot;Результат найден!&quot;);
                return persons[i];
            }
        }

        Console.WriteLine(&quot;Человека с таким ID не существует!&quot;);

        return null;
    }
}

abstract public class ID { private List<string> ids = new List<string>(); //Список существующих ID

    protected string CreateID(int format = 4)
    {
        Random rnd = new Random();

        string id = &quot;&quot;;

        for (int i = 0; i &lt; format; i++)
        {
            id += rnd.Next(0, 10);
        }

        //Создание ID до тех пор, пока он не будет уникальным
        while (CheckID(id))
        {
            for (int i = 0; i &lt; format; i++)
            {
                id += rnd.Next(0, 10);
            }
        }

        ids.Add(id);

        return id;
    }

    //Проверка уникальности ID
    private bool CheckID(string id)
    {
        for (int i = 0; i &lt; ids.Count; i++)
        {
            if (ids[i] == id)
                return true;
        }

        return false;
    }
}

Можете написать о ошибках и недочётах этого кода, я был бы очень рад пополнить свои знания

aepot
  • 49,560
  • 2
    Советую задать этот вопрос также и на CodeReview. – Глеб Oct 01 '23 at 09:04
  • Всё плохо, всё плохо. Как написали бы специалисты по стилю, у вас фигурные скобки для классов не с тем отступом. – rotabor Oct 01 '23 at 09:18
  • Это при переносе из Visual Studio косяк, сразу и не заметил, там у меня всё нормально, может помимо этих фигурных скобок есть какая-то ещё причина ужасности этого кода или только это? – Hipetile__ Oct 01 '23 at 09:23
  • 4
    Вспомнился один анекдот. Прораб говорит пожарному инспектору: "У нас всё в порядке, недавно нас проверяли!". "Вижу пожарный щит. Хотите, по одной лопате 10 замечаний напишу? 1. Черенок не струганый. 2. Черенок не крашеный. 3. Лопата ржавая.". "Хватит, хватит!" - прораб выбрасывает лопату за забор: "Пишите одно замечание: нет лопаты". – rotabor Oct 01 '23 at 09:25
  • В общем я так понимаю "профессионалы" не очень охотно любят указывать на ошибки в коде, либо просто не хотят детально разбираться в нём. "Всё плохо", а что именно плохо - это уже ты сам догадывайся) – Hipetile__ Oct 01 '23 at 09:29
  • Пишу, пишу, ждите ответа – rotabor Oct 01 '23 at 09:30
  • Поскольку ID уникальный, лучше поиск делать не перебором списка за O(n), а брать за O(1) нужного человека по ID из словаря формата ID -> Person. – CrazyElf Oct 01 '23 at 11:14
  • 2
    Используйте возможности IDE. Code analysis. Анализаторы кода могут выявлять множество недочётов и даже предлагать способы их исправления. По умолчанию они включены не все. В файле проекта добавьте <AnalysisMode>all</AnalysisMode>, чтобы активировать все. Ворнингов на ваш код станет выдаваться намного больше. Конечно, не все их нужно исправлять, как там будет рекомендовано, но рассмотреть стоит. – Alexander Petrov Oct 01 '23 at 16:32

2 Answers2

3

Малая толика, по порядку строчек:

  1. Для какой цели Person наследует ID?
  2. Почему в 1 Person список persons? Это должно быть отдельно.
  3. Поля и свойства, как вариант, пойдут. Хотя кодируется это проще
private string name;
public string Name { get { return name; } set { name = value; } }

-->

public string Name { get; set; }

  1. Зачем в конструкторе такие значения по умолчанию? Как минимум, с какой-то начальной информацией объект должен инициализироваться. Возможно, нужны несколько конструкторов с разным набором параметров.
  2. Что-то выводить в конструкторе в консоль - странно. Сделайте протоколирование.
  3. Вместо PrintInfo можно переопределить стандартный метод ToString.
  4. Поиск по идентификатору нужно не перебором делать, а использовать какой-то имеющийся метод. Опять же, никакого вывода в консоль.
  5. Идентификатор нужно генерировать не случайный, а по порядку. И вообще, в чём в нём смысл в данной реализации? Можно просто использовать индекс в массиве или списке persons.

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

rotabor
  • 4,251
  • Пример не очень хороший, но всегда хотел реализовать подобное.
    1. ID изначально хотел сделать закрытым, это точно надо исправлять
    2. Над этим тоже думал, но не знал куда куда стоит поместить список
    3. Думал о том, что нужно разделить конструкторы, но подумал, что так лучше выглядит
    4. Этого термина не знаю, потом посмотрю
    5. Хорошая идея, исправлю
    6. В данном случае бесполезно, но иногда может быть необходимо

    В общем я понял свои ошибки, спасибо за помощь

    – Hipetile__ Oct 01 '23 at 09:49
  • Но ты всё равно молодец, для начала. Советую просто побольше читать. Там и примеры найдутся. И изучать документацию https://learn.microsoft.com/en-us/dotnet/. Вот пример вопроса, подобного твоему https://ru.stackoverflow.com/questions/1543382/%d0%9c%d0%b5%d1%82%d0%be%d0%b4%d1%8b-object-%d0%b2-c#comment2776754_1543382. – rotabor Oct 01 '23 at 09:52
  • И ещё вопрос возник, какой сервис/сайт лучше использовать для проверки кода? – Hipetile__ Oct 01 '23 at 09:56
  • И ещё очень важный вопрос, как сделать свойство, которое можно изменить в конструкторе, но после менять нельзя? Просто readonly для свойств не работает, а если убрать сеттер, то в конструкторе не получится присвоить значение – Hipetile__ Oct 01 '23 at 09:58
  • "какой сервис/сайт лучше использовать для проверки кода?" - я не знаю. В комментариях к вопросу написано. "как сделать свойство, которое можно изменить в конструкторе, но после менять нельзя?" - init https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/init. Советую начать с этого https://ru.stackoverflow.com/questions/416584/%d0%9a%d0%bd%d0%b8%d0%b3%d0%b8-%d0%b8-%d1%83%d1%87%d0%b5%d0%b1%d0%bd%d1%8b%d0%b5-%d1%80%d0%b5%d1%81%d1%83%d1%80%d1%81%d1%8b-%d0%bf%d0%be-c. Лично я рекомендую "Джозеф Албахари. С# 9.0 Справочник. Полное описание языка". – rotabor Oct 01 '23 at 10:04
2

Из того, что не было замечено в других ответах:

  1. Вывод на консоль не должен быть ответственностью модельного класса Person. Класс не должен знать, что его хотят вывести именно на консоль, а не, например, в Windows-приложении или в браузере.

  2. Класс Person не должен являться наследником класса ID, так как он не является идентификатором, а всего лишь содержит его.

  3. Хранение списка всех существующих ID не отскалируется на случай, если ваши данные хоть как-то распределены, или, например, вам понадобится сохранение списка на диск между запусками программы. Вам придётся делать сложные трюки, чтобы всё работало как надо.

  4. Агрегация строки в цикле (for (int i = 0; i < format; i++) id += ... является антипаттерном. Используйте StringBuilder.

  5. Для логирования используйте не вывод на консоль, а устоявшиеся механизмы логирования (не сейчас, а когда программа разрастётся до хотя бы 10 классов).

VladD
  • 206,799