【问题标题】:C#: How to handle accessing of a property of a computed public get/set accessorC#:如何处理对计算的公共 get/set 访问器的属性的访问
【发布时间】:2017-11-05 10:11:08
【问题描述】:

抱歉,问题太长了!我一直在尝试使用 get/set 访问器,但遇到了问题。

举个例子,我有一个 Vector2D 类,它有私有的双精度 x 和 y 值以及这些值的公共访问器 X 和 Y。我还有一个公共方向属性(自定义类型角度,它本身具有公共双度数和弧度属性)。这个 Direction 属性有一个 get 访问器,它根据 X 和 Y 的值返回一个新的 Angle 对象,以及一个 set 访问器,它根据新的角度值传入。

因此,如果您有一个名为 vector 的 Vector2D,则可以使用 vector.Direction = new Angle(0),它可以正常工作。但自然也可以写成 vector.Direction.Degrees = 0。这不会导致错误,但也不能按预期工作,因为向量的 x 和 y 值没有更新。

经过思考,我明白为什么会发生这种情况。当你编写vector.Direction.Degrees时,它使用Vector2D中的get访问器,它根据X和Y返回一个新的Angle,然后它访问Degrees属性及其set that 对象上的 em> 访问器,而不是原始矢量对象上 Direction 属性的 set 访问器。换句话说,vector.Direction 上的 set 访问器根本不会在该场景中使用,因此 x 和 y 值不会更新。我想这是有道理的。

您可以访问 vector.Direction.Degrees 并尝试将其设置为不同的值,但实际上这并没有做任何事情,这显然令人困惑。但我也看到这种行为是有意的。我的问题是,有什么好的方法来处理这个问题?

提前致谢!

编辑 - 这是我的类定义的相关部分:

Vector2D 类

    private double x;
    private double y;

    public double X { get => x; set => x = value; }
    public double Y { get => y; set => y = value; }

    public Angle Direction
    {
        get
        {
            return new Angle(X, Y);
        }
        set
        {
            double previousMagnitude = Magnitude;

            X = Math.Cos(value.Radians) * previousMagnitude;
            Y = Math.Sin(value.Radians) * previousMagnitude;
        }
    }

【问题讨论】:

  • 尝试重载 = 运算符以使用 set 函数。
  • 你能在问题中显示你的类定义吗?可能可以对其进行修改以使其正常工作。
  • 这个问题确实需要代码来说明你在问什么。
  • @SvSv 在 C# 中没有重载赋值。

标签: c# vector get set accessor


【解决方案1】:

(最)正确的做法是使 Angle 不可变,这样它的 Degrees 和 Radians 在创建后就无法更改。您可能需要静态工厂方法 Angle.FromDegrees() 和 Angle.FromRadians(),因为度数和弧度都是双倍的,因此您不能使用 .ctor 重载。

否则,您需要在 Angle 上创建 Changed 事件,将 Vector2D 订阅到此事件,并在每次设置 Degrees 或 Radians 时引发它。当 Vector2D.Angle 被重新分配时也取消订阅......这似乎是一个巨大的矫枉过正,尤其是。如果可以在 Vectors 之间共享 Angle 对象。

【讨论】:

    【解决方案2】:

    由于每次访问它时都会返回一个新的 Direction 值,我建议不要在 Direction.Degrees 和 Direction.Radians 中设置公共集,如下所示:

    public double Degrees
    {
      get { /* return degrees */ }
      private set { /* set degrees, but only from somewhere in the struct, for example the constructor */ }
    }
    

    并像这样使用它:

    public Angle(double X, double Y)
    {
      this.Degrees = /*do computation based on X and Y*/;
      this.Radians = /*do computation...*/
    }
    

    由于保护级别导致属性不可访问而给出错误:

    myVector2D.Direction.Degrees = x;
    

    作品:

    myVector2D.Direction = new Angle(x, y);
    

    这样您可以强制您的用户使用 Vector2D.Direction 的集合而不是 Angle.Degrees 的集合,这样您就可以检测到任何变化并做出反应。

    对于任何格式错误,我在移动设备上表示抱歉。

    【讨论】:

      猜你喜欢
      • 2017-09-15
      • 2012-08-13
      • 2011-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多