Свойство в зависимости от другого свойства, появляется ошибка

#c# #properties

Вопрос:

Такова ситуация, у меня есть класс с двумя свойствами. Если значение Sex равно нулю, то оно устанавливается в зависимости от значения SexString, проблема заключается в доступе к значению Sex, оно ошибается, когда я пытаюсь получить к нему доступ. Есть какие-нибудь идеи о том, что я делаю не так?

 public class Person

public string SexString { get; set; }

public int? Sex 
{
    get { return this.Sex.Value; }
    set 
    {
        if (value == null)
        {
            if (this.SexString.Trim().ToLower() == "female") 
            {
                this.Sex = 1; 
            }
            else if (this.SexString.Trim().ToLower() == "male") 
            { 
                this.Sex = 0; 
            }
            else 
            { 
                this.Sex = 3; 
            }
        }
        else if (value <= 3 amp;amp; value >= 0) 
        {
            this.Sex = value; 
        }
        else 
        { 
            this.Sex = 3; 
        }
    } 
}
 

Комментарии:

1. return this.Sex.Value; причины переполнения стека : this.Sex вызовы this.Sex , которые вызывают this.Sex и т. Д. Используйте резервное поле (скажем, int? m_Sex ), чтобы разорвать этот порочный круг вызовов

Ответ №1:

У вас проблема с переполнением стека: всякий раз, когда вы звоните

 this.Sex
 

внутри Sex свойства он начинает вызывать Sex свойство, которое вызывает this.Sex , которое вызывает Sex и т. Д.
Попробуйте использовать резервное поле:

 private int? m_Sex;

public int? Sex {
  get => m_Sex.HasValue ? m_Sex.Value : 3;
  set {
    if (value == null) 
      if ("female".Equals(SexString, StringComparison.OrdinalIgnoreCase)) 
        m_Sex = 1;
      else if ("male".Equals(SexString, StringComparison.OrdinalIgnoreCase)) 
        m_Sex = 2; //TODO: check this value: is it 0 or 2?
      else
        m_Sex = 3;
    else if (value >= 0 amp;amp; value <= 3)
      m_Sex = value;
    else
      m_Sex = 3; 
  } 
}
 

Примечание: Взгляните на ISO/IEC 5218стандартные половые коды:

  • 0 = Неизвестно
  • 1 = Мужчина
  • 2 = Женщина
  • 9 = Не применимо

Может быть, вам не стоит изобретать свои собственные коды? Если вы придерживаетесь стандарта, вы можете легко реализовать Sex свойство:

 private int m_Sex;

public int Sex {
  get => m_Sex;
  set {
    m_Sex = value >= 0 amp;amp; value <= 2 || value == 9
      ? value
      : throw new ArgumentOutOfRange(nameof(value)); 
  }
}
 

Что касается SexString , вы можете получить его из m_Sex :

 public string SexString {
  get => m_Sex == 0 ? "Unknown"
       : m_Sex == 1 ? "Male"
       : m_Sex == 2 ? "Female"
       : "Not applicable";
  set {
    if ("unknown".Equals(value, StringComparison.OrdinalIgnoreCase) || 
        "not known".Equals(value, StringComparison.OrdinalIgnoreCase) ||
        "?".Equals(value, StringComparison.OrdinalIgnoreCase))
      m_Sex = 0;
    else if ("male".Equals(value, StringComparison.OrdinalIgnoreCase) ||
             "man".Equals(value, StringComparison.OrdinalIgnoreCase) ||
             "m".Equals(value, StringComparison.OrdinalIgnoreCase))
      m_Sex = 1;
    else if ("female".Equals(value, StringComparison.OrdinalIgnoreCase) ||
             "woman".Equals(value, StringComparison.OrdinalIgnoreCase) ||
             "w".Equals(value, StringComparison.OrdinalIgnoreCase) ||
             "f".Equals(value, StringComparison.OrdinalIgnoreCase))
      m_Sex = 2;
    else if (string.IsNullOrWhiteSpace(value) ||
             "-".Equals(value, StringComparison.OrdinalIgnoreCase) ||
             "Not applicable".Equals(value, StringComparison.OrdinalIgnoreCase))
      m_Sex = 9;
    else
      throw new ArgumentException("Not a valid sex definition", nameof(value));   
  }
}