注意:该示例使用类和结构的简化版本。实际的类和结构来自 Unity 事件系统,这里(类)和这里(结构)
我有一个结构,带有清除功能,可以清除其中的所有信息:
public struct MyResult
{
public float index;
public int depth;
public void Clear()
{
index = 0;
depth = 0;
}
}
然后我有一个使用它的类:
public class MyClass
{
public MyResult result { get; set; }
// Wasn't a property but a field in the original question
// I simplified the classes too much, sorry.
}
现在我有一个MyClass
实例,我调用theInstance.result.Clear();
但这并没有将index
和depth
设置为零。如果我检查theInstance.result.index
它仍然是明确呼叫之前的状态。但是,如果我这样做
theInstance.result = new MyResult() { index = 0, depth = 0 }
它确实有效。
现在我不明白为什么清除方法不起作用。谁能解释一下?
编辑:我简化了太多,MyClass
的结果是一个属性,这解释了为什么我会得到这种行为。
实际上,您展示的内容有效...出于不良原因:
var theInstance = new MyClass();
theInstance.result.index = 123;
theInstance.result.depth = 456;
theInstance.result.Clear();
System.Console.WriteLine(theInstance.result.index);
System.Console.WriteLine(theInstance.result.depth);
输出0
和0
。但是,如果字段成为属性 ( {get;set;}
),或者如果将其放入局部变量中,它的行为将有所不同。
从根本上说,你应该避免可变结构,除非你真的知道什么和为什么。此处的正确方法是:
- 使
MyResult
成为class
,或 - 使
MyResult
不可变
如果要在此处使用struct
,适当的实现可能是:
public struct MyResult
{
private readonly float index;
private readonly int depth;
public float Index { get { return index; } }
public int Depth { get { return depth; } }
public MyResult(float index, int depth)
{
this.index = index;
this.depth = depth;
}
public override bool Equals(object obj)
{ /* not shown, but implemented */ }
public override int GetHashCode()
{ /* not shown, but implemented */ }
public override string ToString()
{ /* not shown, but implemented */ }
}
public class MyClass
{
public MyResult Result { get; set; }
}