更改类对象属性C#

时间:2018-07-30 03:31:57

标签: c#

如果我有一个自定义类Vector3并且我有一个类对象Myobject,该对象使用vector3类作为属性,并且设置了新的向量 myobject.pos = new vector3(x,y,z); set在这种情况下将按预期触发Debug.Log("set"),但是如果我不想创建新的向量,我只想更改x但仍然有set触发了我想做的myobject.pos.x = x,但这不会触发set中的MyObject,但是我的set类中的vector3对于x修复此问题后,当我仅更改set的“ sub属性” x时,将触发MyObject中的vector3

public class MyObject{
        private Vector3 p_pos = new Vector3(0, 0, 0);
        public Vector3 pos
        {
            get { return (p_pos); }
            set
            {
                Debug.Log("set");
                p_pos = value;
            }
        }
}

我想到的唯一方法是在MyObject类中创建一个单独的方法,例如MyObject.SetPosX(x)

public void SetPosX(double _x)
{
    Debug.Log("set");
    p_pos.x = _x;
}

但这不是一种很干净的方法,因此最好使用其他解决方案。

2 个答案:

答案 0 :(得分:1)

我认为可以更结构化的方式实现它的方式是允许Vector3在属性更改时通知某人。我的对象类将在必要时监听并做出反应。 在您提供的代码中,它看起来像是开销,但实际上,这取决于实际情况。

代码在下面

using System;
using System.Diagnostics;

public class Program
{
    public static void Main()
    {
        MyObject myObject = new MyObject();
        Vector3 vector3 = new Vector3(1, 1, 1);
        myObject.p_pos = vector3;
        myObject.p_pos.X = 5;
        Console.ReadLine();
    }
}


public class Vector3
{
    public Vector3(double x, double y, double z)
    {
        X = x; Y = y; Z = z;
    }

    private double _x;
    private double _y;
    private double _z;

    public double X
    {
        get
        {
            return _x;
        }
        set
        {
            _x = value;
            OnPropertyChanged(EventArgs.Empty);
        }
    }
    public double Y
    {
        get
        {
            return _y;
        }
        set
        {
            _y = value;
            OnPropertyChanged(EventArgs.Empty);
        }
    }
    public double Z
    {
        get
        {
            return _z;
        }
        set
        {
            _z = value;
            OnPropertyChanged(EventArgs.Empty);
        }
    }

    public event EventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(EventArgs e)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, e);
        }
    }
}

public class MyObject
{
    private Vector3 _p_pos = null;

    public Vector3 p_pos { get
        {
            return _p_pos;
        }
        set
        {
            if (_p_pos != null)
                _p_pos.PropertyChanged-= _p_pos_PropertyChanged;
            _p_pos = value;
            _p_pos.PropertyChanged += _p_pos_PropertyChanged;

        }
    }

    private void _p_pos_PropertyChanged(object sender, EventArgs e)
    {
        Console.Write("_p_pos_PropertyChanged");
    }
}

另一种更可取的方法是使vector3不可变,因此每次需要更改值时,都必须创建vector3的新实例。这样一来,您就可以保留vector3的轻量级版本,并且仍然可以控制其值。

答案 1 :(得分:0)

由于似乎无法回答那样的原因,我给它一个机会。

public class TestClass
{
    private Vector3 _v = 0;
    public Vector3 V { get { return _v; } set { _v = value; } }

    void DoSomething ()
    {
        V = new Vector3 (2, 0, 0); // This will trigger 'set'.
        V.x = 2;                   // This will not.
    }
}

如果具有Vector3属性并设置其特定值,则可以在Vector3类本身内设置值,但不影响对所述Vector3的分配/引用。为了更改其x值,请勿为“ V”设置新的Vector3或其他Vector3。正如您已经知道的,一种避免这种情况的方法就是简单地使用一种方法来更改“ V”的值并触发您的额外代码。另一个可能是拥有自己的类,该类会在属性更改时触发您的额外代码(对于Vector3不太可能)。

如果您只想跟踪对Vector3的更改,则必须创建一个值Watcher类,该类将在更新中触发以检测要跟踪的值的更改。要创建此代码,可能会非常复杂,并且至少要使用lambda表达式和泛型,甚至可能会在Unity中通过将全局基类用于应继承自MonoBehavior的所有内容,甚至使用Unity中的整个代码结构。