使值类型保持同步、依赖项属性、引用、事件或重新设计
本文关键字:事件 引用 属性 类型 依赖 同步 | 更新日期: 2023-09-27 18:36:39
问题:
我有一个值类型(结构),需要保存在由不同类更新的类中。
有效解决此问题的"C#"方法是什么?
方法
我在下面放了基本的"归结"代码。似乎可以通过 3 种方式解决:
- 使"矩阵"成为依赖属性
- 发送"模型"而不是"矩阵"
- 引发控制器订阅的模型更改事件,然后更新 model.matrix
- 这种方法
我对 C# 相对较新,并且来自C++背景,我只会发送一个指向位置的指针(实际上似乎是 4)。然而,它感觉非常"非C#",回头看感觉像"未设计"!
然而,我的假设是 1:d ependency 属性(看起来像"C#"方式)似乎它们或多或少以相同的方式回避设计,我担心间接程度。
我目前对 2 的问题是修饰符负责更新"矩阵",他们实际上不需要了解模型中的其他所有内容,理想情况下甚至不需要处理它。
3感觉像是2的手卷版本,但感觉会更有效率
关于数据:
"矩阵"的多个实例将被大量读取,但一次也只会写入 1/2,最多在鼠标移动事件期间。
示例代码
class Model
{
glm.mat4 position; //mat4 is a struct i.e. a value type
}
class MouseControll
{
MatrixModifiyer Modifier = new MatrixModifiyer()
MouseControll(Model model)
{
Modifier.BindToMatrix(model.matrix);
}
//invoke modifier based on mouse events
}
class InterfaceControll
{
MatrixModifiyer Modifier = new MatrixModifiyer()
InterfaceControll(Model model)
{
Modifier.BindToMatrix(model.matrix);
}
//invoke modifier based on button events
}
class MatrixModifiyer
{
glm.mat4 camera; //how do I have position in sync with camera?
glm.vec2 position;
void BindToMatrix(mat4 matrix)
{
camera = matrix;
}
void PanMatrix()
{
//modify matrix params
position = ...
CalculateNewMatrix();
}
void CalculateNewMatrix()
{
//calculat new matrix;
camera = translate(camera, position)
...
//at this point I want model.matrix to be updated
}
glm.mat4 GetMatrix()
{
return camera;
}
}
class App
{
void Start()
{
Model aModel = new Model();
InterfaceControll interface = new InterfaceControll(aModel);
MouseControll interface = new MouseControll(aModel);
//register mouse controll with mouse events
//register interface control with button events
}
}
这里的主要关注点是你对 C# pass-by-* 语义的理解。使用 C#,所有参数都是按值传递的,而不是按引用传递的,碰巧引用类型的值是它的内存位置,因此传递的值始终指向引用类型的同一实例。我假设您希望能够传递您的值类型,并且所有消费者都始终意识到它的变化?
我认为对此的最佳设计是使用容器引用类型,例如,在您的情况下,可能是这样的:
class GlmParameters
{
public glm.mat4 position { get; set; }
}
或者也许只是传递您的Model
类型,因为这实际上是它已经是:
class MatrixModifier
{
private Model _model;
void BindToMatrix(Model model)
{
_model = model;
}
void PanMatrix()
{
_model.position = //
CalculateNewMatrix();
}
void CalculateNewMatrix()
{
translate(_model);
}
}
要考虑的另一个副作用是,由于按值传递语义,理想情况下值类型应该是不可变的:
struct MyImmutableStruct
{
private readonly int _value;
public MyImmutableStruct(int value)
{
_value = value;
}
public int Value { get { return _value; } }
}
让我们看看这个实际操作:
var first = new MyImmutableStruct(1);
var second = first;
Console.WriteLine(first.Value); // Prints 1
Console.WriteLine(second.Value); // Prints 1
与。
struct MyMutableStruct
{
private int _value;
public MyMutableStruct(int value)
{
_value = value;
}
public int Value { get { return _value; } set { _value = value; } }
}
var third = new MyMutableStruct(1);
var fourth = third;
// Set a new value.
fourth.Value = 2;
Console.WriteLine(third.Value); // Still prints 1
Console.WriteLine(fourth.Value); // Prints 2
您会注意到,由于fourth
是third
的副本,因此它不是同一个实例,因此不会反映对fourth
实例的任何更改。当然,您可以通过改用引用类型或在传递值舍入时使用ref
参数来解决此问题。