exception StackOverflowException
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.216] |
|
|
exception StackOverflowException
|
Сообщ.
#1
,
|
|
|
|
Мне выводит следующую исключительную ситуацию StackOverflowException и ругается на этот участок кода.
![]() ![]() private bool isNameCorrect(string name) { char[] tempName = name.ToCharArray();//StackOverflowException Я думаю, что нужно массив char[] tempName объявить за пределами метода, перед тем как метод isNameCorrect нужно вызвать. И вместо строки передавать символы в качестве параметров из массива char[] tempName. Но мне кажется, это не самый лучший вариант исправления ошибки. Как лучше решить данную проблему? Весь код ![]() ![]() 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); } } |
|
Сообщ.
#2
,
|
|
|
|
Потому что ты сам зацикливаешь свой пример.
![]() ![]() public string Name { get { return Name; // Бесконечный цикл, проперти вызывает сама себя } set { if (isNameCorrect(value)) Name = value; else Console.WriteLine("Имя не должно содержать цифры и другие символы."); } } ![]() ![]() string name = string.Empty; public string Name { get { return name ; } set { if (isNameCorrect(value)) name = value; else Console.WriteLine("Имя не должно содержать цифры и другие символы."); } } Добавлено ![]() ![]() //Валидацию лучше вынести в наружный класс //Код написан очень плохо. Нужно переписать. После написания кода нужно проверять его работоспособность //а то судя по коду вы не понимаете что делает данный код 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); } } |
|
Сообщ.
#3
,
|
|
|
|
спасибо за помощь. Я просто чего то не умудрился проверить код. Я не понял одного момента. В каком случае использовать свойства вместо переменных членов класса? Когда необходимо автопроперти и нету дополнительных критериев для проверки получаемых данных?
|
|
Сообщ.
#4
,
|
|
|
|
Property это своего рода аналог функций Get, Set. Где функции с параметром Get должны возвращать результат, а Set - устанавливать его.
Вместо место такого кода ![]() ![]() string name = string.Empty; public string Name { get { return name ; } set { name = value; } } ![]() ![]() string name = string.Empty; public string GetName() { return name; } public void SetName(string name) { name = value; } ![]() ![]() public string Name { get; set; } //Использование Name = "Petya"; Console.WriteLine(Name); ![]() ![]() Person a = new Person("111", "1111", "a"); a.Show(); Person b = new Person("111", "1111", "a"); b.Show(); Добавлено P.S. Если не знаешь как писать, лучше спросить об этом или поискать. Писать либо что это хуже чем ничего не писать. Я форуме много людей которые помогут безвозмездно если человек что-то делает. И помогут за деньги если человек не хочет ничего знать, а хочет чтоб вместо него это сделали. Если не получается что-то можешь написать мне в личку. Если я буду знать ответ и как можно сделать то или иное, я помогу. Если это будет выходить за грани моих знаний, поможет кто то другой. |
|
Сообщ.
#5
,
|
|
|
|
Craft, подправил код согласно твоим замечаниям. Из выше перечисленных замечаний, я понял, что стоит прочитать мне про свойства и строки. Может, что то еще?
Класс Person ![]() ![]() 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 ![]() ![]() 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(); } } |
|
Сообщ.
#6
,
|
|
|
|
mastermedia Впечатляет. Как для начинающего очень даже ничего. Только есть одно небольшое замечание. Код
![]() ![]() 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. Для этого и придумали инкапсуляцию. Можешь приступать к делегатам и ивентам. Если понял как устроен код, и почему так а не иначе. Тогда только закрепляй на примерах то что выучил. Удачи. |
|
Сообщ.
#7
,
|
|
|
|
Craft, спасибо за помощь. Пока, что делегаты и ивенты подождут. Я сейчас разбираюсь в наследование, виртуальные методы, абстрактные методы и класс object. Это кусок кода из упражнения по наследованию, точнее один класс который будет использоваться.
|
|
Сообщ.
#8
,
|
|
|
|
По поводу пропертей и функций get/set: По моему(и не только) мнению, когда используется проперти, то я подразумеваю, что установка значения и получение значения делается сравнительно быстро. Если же там (обычно в set-е) происходят какие-то весомые действия, то стоит сделать пару: проперти только доля чтения и метод SetSomeValue(SomeType value);
По поводу стилистики именования: - рекомендую именовать проперти UpperCamelCase-ом. Т.е. с большой буквы и без префиксов. - тоже самое касается названий методов. - нестатические поля, по моему мнению, должны быть исключительно приватными и их, как раз, нужно именовать lowerCamelCase-ом и можно с префиксом. - для расшаривания приватных полей для наследников .NET принято использовать protected проперти. |