在类中获取/设置结构或类的成员

本文关键字:成员 结构 获取 设置 | 更新日期: 2023-09-27 18:10:26

如果我有一个StructClass,让我说我使用一个Vector2(它有两个成员,float Xfloat Y),我应该如何正确地获得/设置它的方法在一个类?

这是我现在知道的代码:

public class MyClass
{
    private Vector2 vector; //Has to be private
    public Vector2 Vector
    {
        get { return vector; }
        set { vector = value; }
    }
}

但是如果我想用set方法编辑Vector2的成员(或某些成员)该怎么办?这就是我想要的:

set.X
{
    vector.X = value.X;
}
set.Y
{
    vector.Y = value.Y;
}

它将被简单地称为Vector.X = 5。我想到了另一种选择,使用public float VectorX { set { vector.X = value; } }之类的东西,但我更喜欢更合乎逻辑和面向对象的方式。是吗?

在类中获取/设置结构或类的成员

Vector2是一个类还是一个结构体有很大的区别。

由于Vector2是一个类,您可以简单地执行

obj.Vector.X = 5;

public class MyClass
{
    private Vector2 _vector; //Has to be private
    public Vector2 Vector
    {
        get { return vector; }
        set { vector = value; }
    }
}

但是,如果Vector2 结构体,则不能修改get的返回值。如果你尝试,你会得到一个编译错误:

不能修改…的返回值。因为它不是一个变量

您可以使用

建议的方法来解决这个问题
public float VectorX
{
    get { return _vector.X; }
    set { _vector.X = value; }
}
public float VectorY
{
    get { return _vector.Y; }
    set { _vector.Y = value; }
}

或者您可以为Vector2提供一个包装类,如:

class Vector2Wrapper
{
    public Vector2 Vector;
}
然后在MyClass中存储Vector2Wrapper,例如
public class MyClass
{
    private Vector2Wrapper _vector2Wrapper;
    public Vector2Wrapper VectorWrapper
    {
        get { return _vector2Wrapper; }
        set { _vector2Wrapper= value; }
    }
}

然后你可以把它修改成

obj.VectorWrapper.Vector.X = 5;

您不能指定一个子方法来处理该部分集合,因为该集合由Vector类处理,因此超出了您的作用域。当有人调用Myobject.Vector时,他们正在调用您的get函数,但是当它移动到.X时,他们正在调用Vector.get_X函数。

通过使用ilasm工具查看编译后的代码,这可能更容易看到,它揭示了实际的方法调用你的属性来制作糖。

现在,您可以做的是换行某些属性,如前所述。结果就像这样。

public class MyClass
{
    private Vector2 _vector; //Has to be private
    public Vector2 Vector
    {
        get { return vector; }
        set { vector = value; }
    }
    public float VectorX
    {
        get { return _vector.X; }
        set { _vector.X = value; }
    }
    public float VectorY
    {
        get { return _vector.Y; }
        set { _vector.Y = value; }
    }
}

另一个选项可能是在Vector类中使用INotifyPropertyChanged模式,每次更改都会引发一个事件,然后MyClass可以侦听并做出反应,从而在子元素更新时应用逻辑。

也可以选择使用索引器属性

public class MyClass
{
    public enum Axis { X, Y }
    private Vector2 _vector; //Has to be private
    public Vector2 Vector
    {
        get { return vector; }
        set { vector = value; }
    }
    public float this[Axis axis]
    {
        get { return axis == Axis.X ? vector.x : vector.y; }
        set
        {
            if(axis == Axis.Y)
            {
                // Special logic here
                vector.Y = value;
            }
            if(axis == Axis.X)
            {
                // Special logic here
                vector.X = value;
            }
        }
    }
}

因为Vector2是一个结构体,所以你得到了一个COPY。您需要使用setter来设置新的Vector2。有两种方法:

Vector2 v = myClass.Vector; //get a copy of the vector
v.X = 5f; // change its value
myClass.Vector = v; // put it back

我不太喜欢下面这个句子,但它是一个句子:

    myClass.Vector = new Vector2(2f, myClass.Vector.Y)

在MyClass中,你可以创建一个只设置X值的属性:

public float X {
    get { return Vector.X; }
    set {
        Vector2 v = Vector;
        v.X = value;
        Vector = v;
    }
}

(Vector可以是一个自动属性)