На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS

Дорогие друзья! Поздравляем вас с Новым 2026 годом!

Всем удачи, успеха и благополучия!

msm.ru
  
> exception StackOverflowException
    Мне выводит следующую исключительную ситуацию StackOverflowException и ругается на этот участок кода.
    ExpandedWrap disabled
       private bool isNameCorrect(string name)
              {
                  char[] tempName = name.ToCharArray();//StackOverflowException

    Я думаю, что нужно массив char[] tempName объявить за пределами метода, перед тем как метод isNameCorrect нужно вызвать. И вместо строки передавать символы в качестве параметров из массива char[] tempName. Но мне кажется, это не самый лучший вариант исправления ошибки. Как лучше решить данную проблему?


    Весь код
    ExpandedWrap disabled
      class Person
          {
              public string Name
              {
                  get
                  {
                      return Name;
                  }
       
                  set
                  {
                      if (isNameCorrect(value))
                          Name = value;
                      
                      else
                          Console.WriteLine("Имя не должно содержать цифры и другие символы.");
                  }
              }
       
              public string Surname
              {
                  get
                  {
                      return Surname;
                  }
       
                  set
                  {
                      if (isSurnameCorrect(value))
                          Surname = value;
       
                      else
                          Console.WriteLine("Фамилия не должна содержать цифры и другие символы.");
                  }
              }
       
              public string Age
              {
                  get
                  {
                      return Age;
                  }
                  set
                  {
                      if (isAgeCorrect(value))
                          Age = value;
                      
                      else
                          Console.WriteLine("Возраст не должен содержать букв и других символов.");
                  }
              }
       
              private bool isNameCorrect(string name)
              {
                  char[] tempName = name.ToCharArray();//StackOverflowException
                  foreach (char x in tempName)
                  {
                      if (Char.IsLetter(x))
                      {
                          return true;
                      }
       
                      else
                      {
                          break;
                      }
                  }
       
                  return false;
              }
       
              private bool isSurnameCorrect(string surname)
              {
                  char[] tempSurname = surname.ToCharArray();
                  
                  foreach (char letter in tempSurname)
                  {
                      if (Char.IsLetter(letter))
                      {
                          return true;
                      }
       
                      else
                      {
                          break;
                      }
                  }
       
                  return false;
              }
       
              private bool isAgeCorrect(string age)
              {      
                  char[] tempAge = age.ToCharArray();
                  foreach (char num in tempAge)
                  {
                      if (Char.IsLetter(num))
                      {
                          return true;
                      }
       
                      else
                      {
                          break;
                      }
                  }
                  return false;
              }
       
              public Person(string n, string s, string a)
              {
                  if(isNameCorrect(n))
                      Name = n;
                  
                  else
                      Console.WriteLine("Имя не должно содержать цифры и другие символы.");
                  
                  if(isSurnameCorrect(s))
                      Surname = s;
                  
                  else
                      Console.WriteLine("Фамилия не должна содержать цифры и другие символы.");
       
                  if (isAgeCorrect(a))
                      Age = a;
                  
                  else
                      Console.WriteLine("Возраст не должен содержать букв и других символов.");
              }
       
              public void Show()
              {
                  Console.WriteLine("Данные: {0}, {1}, {2}." + Surname, Name, Age);
              }
          }
      Потому что ты сам зацикливаешь свой пример.
      ExpandedWrap disabled
        public string Name
                {
                    get
                    {
                        return Name; // Бесконечный цикл, проперти вызывает сама себя
                    }
         
                    set
                    {
                        if (isNameCorrect(value))
                            Name = value;
         
                        else
                            Console.WriteLine("Имя не должно содержать цифры и другие символы.");
                    }
                }
      перепиши на
      ExpandedWrap disabled
        string name = string.Empty;
        public string Name
                {
                    get
                    {
                        return name ;
                    }
         
                    set
                    {
                        if (isNameCorrect(value))
                            name = value;
         
                        else
                            Console.WriteLine("Имя не должно содержать цифры и другие символы.");
                    }
                }


      Добавлено
      ExpandedWrap disabled
        //Валидацию лучше вынести в наружный класс
            //Код написан очень плохо. Нужно переписать. После написания кода нужно проверять его работоспособность
            //а то судя по коду вы не понимаете что делает данный код
            class Person
            {
                //Бесконечный цикл. Проперти вызывает сама себя вечно.
                //Заменить на переменную string name и присваивать ей значение.
                public string Name
                {
                    get
                    {
                        return Name;
                    }
         
                    set
                    {
                        //Проверка неверная в корне. И она здесь просто лишная. Если объект уже создан, то смысла в этой проверке просто нет.
                        //Тем более она имя "а111" воспримет как истину
                        if (isNameCorrect(value))
                            Name = value;
         
                        else
                            Console.WriteLine("Имя не должно содержать цифры и другие символы.");
                    }
                }
         
                //Та же ошибка что и выше
                public string Surname
                {
                    get
                    {
                        return Surname;
                    }
         
                    set
                    {
                        if (isSurnameCorrect(value))
                            Surname = value;
         
                        else
                            Console.WriteLine("Фамилия не должна содержать цифры и другие символы.");
                    }
                }
         
                //Та же ошибка что и для Name
                public string Age
                {
                    get
                    {
                        return Age;
                    }
                    set
                    {
                        if (isAgeCorrect(value))
                            Age = value;
         
                        else
                            Console.WriteLine("Возраст не должен содержать букв и других символов.");
                    }
                }
         
                private bool isNameCorrect(string name)
                {
                    //Где проверка на то что строка пустая или null? Если же дальше пойдет null
                    //то будет ошибка NullReferenceException.
         
                    //класс string содержит интерфейс IEnumerable , и поэтому запись ниже лишняя  
                    //char[] tempName = name.ToCharArray(); //лишняя запись.
                    // Прочитайте про тип string. Это вам очень нужно
                    foreach (char x in name)
                    {
                        if (Char.IsLetter(x))
                        {
                            //если писать такую запись то нужно вместо return true написать continue,
                            return true;
                        }
         
                        else
                        {
                            //а здесь тогда не break а return false
                            break;
                        }
                    }
         
                    //сдесь нужно возвращать тогда истину, потому что name содержит только буквы
                    return false;
         
                    //Или полность переписать код. Здесь достаточно сделать две проверки.
                    //1) name проверить на пустую строку и на null чтоб не продолжать дальше выполнения если будет истина
                    //2) проверять на !Char.IsLetter(x) и возвращать false. И в самом конце вернуть истину.
         
                }
         
                //Те же ошибки что и для isNameCorrect
                private bool isSurnameCorrect(string surname)
                {
                    char[] tempSurname = surname.ToCharArray();
         
                    foreach (char letter in tempSurname)
                    {
                        if (Char.IsLetter(letter))
                        {
                            return true;
                        }
         
                        else
                        {
                            break;
                        }
                    }
         
                    return false;
                }
         
                //Хуже даже ошибки чем в isNameCorrect. Те же что и в isNameCorrect + те что описаны ниже
                private bool isAgeCorrect(string age)
                {
                    char[] tempAge = age.ToCharArray();
                    foreach (char num in tempAge)
                    {
                        //Проверять возраст на символы это вообще ужас. Истина возвращаеться когда возраст равен например "а"
                        // Написанный код нужно всегда проверять. Этот вообще не работает
                        if (Char.IsLetter(num))
                        {
                            return true;
                        }
         
                        else
                        {
                            break;
                        }
                    }
                    return false;
                }
         
                //Ни в коем случае не называйте переменные n, s и т.д. Если пишете большой проект и пишете не один
                // то как колеги программысти поймут что такое n и s? Будут вмотреть код что вы написали?
                public Person(string n, string s, string a)
                {
                    //Зачем делать дублирование кода если сама проперти Name уже сожержит проверку?
                    //Пусть даже неправильную.
                    //if (isNameCorrect(n))
                    //    Name = n;
         
                    //else
                    //    Console.WriteLine("Имя не должно содержать цифры и другие символы.");
         
                    //if (isSurnameCorrect(s))
                    //    Surname = s;
         
                    //else
                    //    Console.WriteLine("Фамилия не должна содержать цифры и другие символы.");
         
                    //if (isAgeCorrect(a))
                    //    Age = a;
         
                    //else
                    //    Console.WriteLine("Возраст не должен содержать букв и других символов.");
         
                    //Код выше полность не верен
                    //Нужно переписать просто  Name = n; Surname = s; Age = a; поскольку
                    // валидация данных прописана в самих проперти.
                }
         
                public void Show()
                {
                    //Это вообще не скомпилируеться так как "Данные: {0}, {1}, {2}." + Surname сделает конкатенацию строк
                    // а вам нужно три аргумента передать. Плюс здесь совсем лишний.
                    //Единственный плюс что уже используете проверти , а не переменные на которые оны ссылаються
                    Console.WriteLine("Данные: {0}, {1}, {2}." + Surname, Name, Age);
                }
            }
      Сообщение отредактировано: Craft -
        спасибо за помощь. Я просто чего то не умудрился проверить код. Я не понял одного момента. В каком случае использовать свойства вместо переменных членов класса? Когда необходимо автопроперти и нету дополнительных критериев для проверки получаемых данных?
        Сообщение отредактировано: mastermedia -
          Property это своего рода аналог функций Get, Set. Где функции с параметром Get должны возвращать результат, а Set - устанавливать его.
          Вместо место такого кода
          ExpandedWrap disabled
            string name = string.Empty;
            public string Name
                    {
                        get
                        {
                            return name ;
                        }
             
                        set
                        {
                            name = value;
                        }
                    }
          можно написать такой.
          ExpandedWrap disabled
            string name = string.Empty;
            public string GetName()
            {
                return name;
            }
            public void SetName(string name)
            {
                name = value;
            }
          . Property это не нечто магическое. Компилятор вместо тебя создает функции с приставками get, set. Autoproperty стоит использовать когда в сеттере не нужно делать проверку, и когда get возвращает ожидаемое поведение.
          ExpandedWrap disabled
            public string Name { get; set; }
             
            //Использование
            Name = "Petya";
            Console.WriteLine(Name);
          Если нужно добавить проверку в set, или в get то нужно использовать классические проперти. Autoproperty в этом не помогут. У твоем примере проверка в set ничего не даст, так как объект уже создан. Наведу пример если у тебя проверка не пройдет, что будет в результате.
          ExpandedWrap disabled
            Person a = new Person("111", "1111", "a");
            a.Show();
            Person b = new Person("111", "1111", "a");
            b.Show();
          В результате получишь что а и b класс не содержат данных, потому что не сработала проверка для Name, Surname и Age. В итоге ты получаешь предупреждение, например Console.WriteLine("Фамилия не должна содержать цифры и другие символы."); , но это ничего не меняет. У тебя создано два пустых объекта. Объект не должен быть создан если он не прошел верификацию. Это нормально поведение. Поэтому нужно в сеттерах проперти либо бросать исключения в случае некорректных данных, либо требовать от пользователя вводить данные пока он не введет правильные, или вынести проверку на уровень выше, и в случае если данные не корректные вывести об этом сообщение и попросить повторить ввод. Прочитай внимательно что такое свойства. Можешь даже у Рихтера посмотреть что это такое.

          Добавлено
          P.S. Если не знаешь как писать, лучше спросить об этом или поискать. Писать либо что это хуже чем ничего не писать. Я форуме много людей которые помогут безвозмездно если человек что-то делает. И помогут за деньги если человек не хочет ничего знать, а хочет чтоб вместо него это сделали. Если не получается что-то можешь написать мне в личку. Если я буду знать ответ и как можно сделать то или иное, я помогу. Если это будет выходить за грани моих знаний, поможет кто то другой.
            Craft, подправил код согласно твоим замечаниям. Из выше перечисленных замечаний, я понял, что стоит прочитать мне про свойства и строки. Может, что то еще?

            Класс Person
            ExpandedWrap disabled
              class Person
                  {
                      private string name;
                      private string surname;
                      private string age;
               
                      public bool nStatus { get; private set; }
                      public bool sStatus { get; private set; }
                      public bool aStatus { get; private set; }
               
                      private bool isNameCorrect(string tempName)
                      {
                          if (String.IsNullOrEmpty(tempName))
                              return false;
               
                          foreach (char letter in tempName)
                          {
                              if (Char.IsLetter(letter))
                                  continue;
               
                              else
                                  return false;
                          }
               
                          return true;
                      }
               
                      private bool isSurnameCorrect(string tempSurname)
                      {
                          if(String.IsNullOrEmpty(tempSurname))
                              return false;
               
                          foreach (char letter in tempSurname)
                          {
                              if (char.IsLetter(letter))
                                  continue;
               
                              else
                                  return false;
                          }
               
                          return true;
                      }
               
                      private bool isAgeCorrect(string tempAge)
                      {
                          if (String.IsNullOrEmpty(tempAge))
                              return false;
               
                          foreach (char num in tempAge)
                          {
                              if (char.IsDigit(num))
                                  continue;
               
                              else
                                  return false;
                          }
               
                          return true;
                      }
               
                      public string Name
                      {
                          get
                          {
                              return name;
                          }
               
                          set
                          {
                              if (isNameCorrect(value))
                              {
                                  nStatus = true;
                                  name = value;
                              }
                              else
                              {
                                  nStatus = false;
                                  Console.WriteLine("Имя введено не верно. Введите имя заново.");
                              }
                          }
                      }
               
                      public string Surname
                      {
                          get
                          {
                              return surname;
                          }
               
                          set
                          {
                              if (isSurnameCorrect(value))
                              {
                                  sStatus = true;
                                  surname = value;
                              }
               
                              else
                              {
                                  sStatus = false;
                                  Console.WriteLine("Фамилия введена не верно. Введите заново.");
                              }
                          }
                      }
               
                      public string Age
                      {
                          get
                          {
                              return age;
                          }
               
                          set
                          {
                              if (isAgeCorrect(value))
                              {
                                  aStatus = true;
                                  age = value;
                              }
               
                              else
                              {
                                  aStatus = false;
                                  Console.WriteLine("Вы не правильно вели возраст. Введите заново.");
                              }
                          }
                      }
               
                      public void Show()
                      {
                          Console.WriteLine("Имя {0}, фамилия {1}, возраст {2}.", Name, Surname, Age);
                      }
                  }


            Класс Program
            ExpandedWrap disabled
               class Program
                  {
                      static void Main(string[] args)
                      {
                          Person p = new Person();
                          while (!p.nStatus)
                          {
                              Console.Write("Введите имя ");
                              p.Name = Console.ReadLine();
                              Console.WriteLine();
                          }
               
                          while (!p.sStatus)
                          {
                              Console.Write("Введите фамилию ");
                              p.Surname = Console.ReadLine();
                              Console.WriteLine();
                          }
               
                          while (!p.aStatus)
                          {
                              Console.Write("Введите возраст ");
                              p.Age = Console.ReadLine();
                              Console.WriteLine();
                          }
               
                          p.Show();
                      }
                  }
            Сообщение отредактировано: mastermedia -
              mastermedia Впечатляет. Как для начинающего очень даже ничего. Только есть одно небольшое замечание. Код
              ExpandedWrap disabled
                while (!p.nStatus)
                            {
                                Console.Write("Введите имя ");
                                p.Name = Console.ReadLine();
                                Console.WriteLine();
                            }
                 
                            while (!p.sStatus)
                            {
                                Console.Write("Введите фамилию ");
                                p.Surname = Console.ReadLine();
                                Console.WriteLine();
                            }
                 
                            while (!p.aStatus)
                            {
                                Console.Write("Введите возраст ");
                                p.Age = Console.ReadLine();
                                Console.WriteLine();
                            }

              вынеси в отдельную булевскую функцию ValidatePerson. Пользователя вообще не должно волновать как устроена проверка. Наружу делаешь доступными только две функции ValidatePerson и Show(). Все остальные делаешь как private. Для этого и придумали инкапсуляцию.

              Можешь приступать к делегатам и ивентам. Если понял как устроен код, и почему так а не иначе. Тогда только закрепляй на примерах то что выучил. Удачи.
                Craft, спасибо за помощь. Пока, что делегаты и ивенты подождут. Я сейчас разбираюсь в наследование, виртуальные методы, абстрактные методы и класс object. Это кусок кода из упражнения по наследованию, точнее один класс который будет использоваться.
                Сообщение отредактировано: mastermedia -
                  По поводу пропертей и функций get/set: По моему(и не только) мнению, когда используется проперти, то я подразумеваю, что установка значения и получение значения делается сравнительно быстро. Если же там (обычно в set-е) происходят какие-то весомые действия, то стоит сделать пару: проперти только доля чтения и метод SetSomeValue(SomeType value);

                  По поводу стилистики именования:
                  - рекомендую именовать проперти UpperCamelCase-ом. Т.е. с большой буквы и без префиксов.
                  - тоже самое касается названий методов.
                  - нестатические поля, по моему мнению, должны быть исключительно приватными и их, как раз, нужно именовать lowerCamelCase-ом и можно с префиксом.
                  - для расшаривания приватных полей для наследников .NET принято использовать protected проперти.
                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                  0 пользователей:


                  Рейтинг@Mail.ru
                  [ Script execution time: 0,0775 ]   [ 16 queries used ]   [ Generated: 18.01.26, 08:53 GMT ]