[英]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.