c#封装Get/Set

c# encapsulation Get/ Set

寻找有关 Get / Set 的一些说明。我有这个代码,我用它来创建我的对象..但是我想在 lengthwidth 中进行 一些验证 (两者都需要更大比一些数字作为例子)。我相信 Get / Set 是可行的方法,我在更改实例中的字段时使用过它 - 但我如何在实例化阶段执行此操作?

class Room
{
    public Double dblLength;
    public Double dblWidth;

    public Room (Double _dblLength, Double _dblWidth)
    {

        dblLength = _dblLength;
        dblWidth = _dblWidth;
    }

字段转换为属性;在相应的 set:

中实施验证
class Room
{
    private Double m_DblLength;
    private Double m_DblWidth;

    public Room (Double _dblLength, Double _dblWidth) {
      DblLength = _dblLength;
      DblWidth = _dblWidth;
    }

    public Double DblLength {
      get {
        return m_DblLength;
      }
      set {
        //TODO: validation here
        if (value < 0)
          throw new ArgumentOutOfRangeException("value"); 

        m_DblLength = value;
      }
    }

    public Double DblWidth {
      get {
        return m_DblWidth;
      }
      set {
        //TODO: validation here
        if (value < 0)
          throw new ArgumentOutOfRangeException("value"); 

        m_DblWidth = value;
      }
    }

如果你的 class 是不可变的,最简单的是:

class Room
{
    public double Length { get; }
    public double Width { get; }

    public Room(double length, double width)
    {
        // Validation here, for instance throw exception if length <= 0
        Length = length;
        Width = width;
    }
}

使用 C# 6's readonly auto properties.

这是一个基于亚历克斯评论的示例。就我个人而言,我也会去掉下划线和 'dbl' 前缀,但我将它们留在里面以匹配问题。

您不能 return 来自构造函数的失败消息,因此抛出异常。

class Room
  {
  private Double dblLength;
  private Double dblWidth;

  public Room (Double _dblLength, Double _dblWidth)
  {
    if (_dblLength < _dblWidth)
    {
        throw new ArgumentException("length must be more than width");
    }

    dblLength = _dblLength;
    dblWidth = _dblWidth;
  }
}

如果它表明使用您的 class 的程序员不理解它,那么这是合适的。但是,如果很有可能在 运行 时间发生这种情况,您最好在对象中设置一个 'hasError' 标志,以防止它被保存或执行任何操作。

  class Room
  {
    private Double dblLength;
    private Double dblWidth;

    public bool HasError {get;}

    public Room (Double _dblLength, Double _dblWidth)
    {
      if (_dblLength < _dblWidth)
      {
          HasError = true;
      }

      dblLength = _dblLength;
      dblWidth = _dblWidth;
    }

    public Save()
    {
        if (HasError) return;
        // Otherwise do the save;
    }
}

您可以将字段更改为 properties。当您将字段更改为属性后,您可以验证 value,它将设置为相应的 属性,如果不符合要求,您可以抛出异常。

示例:

class Room
    {
        private double _dblLength;
        private double _dblWidth;

        public double DblLength {
            get
            {
                return _dblLength;
            }
            set
            {
                //TODO -> Do validation
                //the keyword value represents the value that you want to pass to the property
                if(value < 0)
                {
                    throw new ArgumentOutOfRangeException("message");
                }

                _dblLength = value;
            }
        }
        public double DblWidth
        {
            get
            {
                return _dblWidth;
            }
            set
            {
                //TODO -> Do validation
                //the keyword value represents the value that you want to pass to the property
                if (value < 1)
                {
                    throw new ArgumentOutOfRangeException("message");
                }

                _dblWidth = value;
            }
        }

        public Room(Double _dblLength, Double _dblWidth)
        {
            DblLength = _dblLength;
            DblWidth = _dblWidth;
        }
    }   

另一件好事是,如果您希望仅在创建实例时设置属性(仅通过构造函数),您可以像这样设置 setter private

class Room
    {
        private double _dblLength;
        private double _dblWidth;

        public double DblLength {
            get
            {
                return _dblLength;
            }
            private set
            {
                //TODO -> Do validation
                //the keyword value represents the value that you want to pass to the property
                if(value < 0)
                {
                    throw new ArgumentOutOfRangeException("message");
                }

                _dblLength = value;
            }
        }
        public double DblWidth
        {
            get
            {
                return _dblWidth;
            }
            private set
            {
                //TODO -> Do validation
                //the keyword value represents the value that you want to pass to the property
                if (value < 1)
                {
                    throw new ArgumentOutOfRangeException("message");
                }

                _dblWidth = value;
            }
        }

        public Room(Double _dblLength, Double _dblWidth)
        {
            DblLength = _dblLength;
            DblWidth = _dblWidth;
        }
    }

这是可能的,因为属性只是 C# 提供给我们的语法糖。编译此代码时,编译器将为每个 属性 创建两个方法 GetSet。因此,如果您在 getter 或 setter 上放置访问修饰符,编译器会考虑到这一点,并且在编译代码时,它会放置您指定的修饰符。但是,如果未指定特定修饰符,编译器将采用 属性 自身的修饰符,在上述情况下,Get 方法将为 public,而 Set 方法将为私人的。编译后代码将如下所示:

class Room
{
    private double _dblLength;
    private double _dblWidth;

    public Room(Double _dblLength, Double _dblWidth)
    {
        SetDblLength(_dblLength);
        SetDblWidth(_dblWidth);
    }

    public double GetDblLength()
    {
        return _dblLength;
    }

    private void SetDblLength(double value)
    {
        if (value < 0)
        {
            throw new ArgumentOutOfRangeException("message");
        }

        _dblLength = value;
    }

    public double GetDblWidth()
    {
        return _dblWidth;
    }

    private void SetDblWidth(double value)
    {
        if (value < 0)
        {
            throw new ArgumentOutOfRangeException("message");
        }

        _dblWidth = value;
    }
}