[英]How to set a specific member of a struct, using indexing in C#
假设我有一个结构:
struct Vector
{
public int X, Y;
// ...
// some other stuff
}
和一个班级:
class Map
{
public Vector this[int i]
{
get
{
return elements[i];
}
set
{
elements[i] = value;
}
}
private Vector[] elements
// ...
// some other stuff
}
我希望能够做类似的事情: map[index].X = 0;
但我不能,因为返回值不是变量。
如果可能的话,我该怎么做?
你应该避免可变的结构。
如果您希望您的类型是可变的,请使用类。
class Vector
{
public int X { get; set; } // Use public properties instead of public fields!
public int Y { get; set; }
// ...
// some other stuff
}
如果要使用结构,请将其设为不可变:
struct Vector
{
private readonly int x; // Immutable types should have readonly fields.
private readonly int y;
public int X { get { return x; }} // No setter.
public int Y { get { return y; }}
// ...
// some other stuff
}
编译器阻止您执行此操作,因为索引器返回对象的副本而不是引用(struct按值传递)。 索引器返回一个副本,您修改此副本并且您根本看不到任何结果。 编译器可以帮助您避免这种情况。
如果你想处理这种情况,你应该使用class或改变你处理Vector的方式。 你不应该修改它的值,而是在构造函数中初始化它的值,更多关于这个主题: 为什么可变结构“邪恶”? 。
将值存储在临时变量中
var v = map [index]; vX = 0; map [index] = v;
要么
要么
让[]运算符返回一个setter类
class Setter {Vector [] Data; int索引; public double X {get {return Data [Index]; } set {Data [Index] = new Vector(value,Data [Index] .Y); }}}
public Setter this [int i] {get {return new Setter(){Data = elements,Index = i}; }}
虽然泛型类在很多方面都能很好地工作,但是它们没有提供任何合理的方法来通过引用访问结构。 这是不幸的,因为在许多情况下,结构集合将提供比类对象集合更好的性能(减少内存占用和改进的缓存局部性)和更清晰的语义。 使用结构数组时,可以使用类似ArrayOfRectangle[5].Width += 3;
的语句ArrayOfRectangle[5].Width += 3;
具有非常明显的效果:它将更新ArrayOfRectangle[5]
字段X
,但它不会影响Rectangle
类型的任何其他存储位置的字段X
需要知道的唯一事情是ArrayOfRectangle
是一个Rectangle[]
,而Rectangle
是一个带有公共int
字段X
。 如果Rectangle
是一个类,并且ArrayOfRectangle[5]
中ArrayOfRectangle[5]
的实例曾经暴露给外部世界,那么很难或不可能确定ArrayOfRectangle[5]
引用的实例是否也被其他一些代码所持有。期望它的实例的字段X
不会改变。 使用结构时可以避免这些问题。
鉴于.net的集合实现的方式,最好的方法通常是制作结构的副本,修改它并将其存储回来。 这样做有点蠢,但是对于不太大的结构,通过使用值类型实现的改进的内存占用和缓存局部性可能超过将数据结构显式复制到数据结构的额外代码。 与使用不可变类类型相比,它几乎肯定是一个重大胜利。
顺便说一句,我想看到的是集合暴露方法,如: OperateOnElement<paramType>(int index, ref T element, ref paramType param, ActionByRef<T,paramType> proc)
,它们将使用适当的元素调用proc
集合以及传入的参数。 在许多情况下,可以在不必创建闭包的情况下调用这样的例程; 如果这样的模式是标准化的,编译器甚至可以使用它来很好地自动生成字段更新代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.