Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用C中的索引设置结构的特定成员#_C#_Struct_Indexing - Fatal编程技术网

C# 如何使用C中的索引设置结构的特定成员#

C# 如何使用C中的索引设置结构的特定成员#,c#,struct,indexing,C#,Struct,Indexing,假设我有一个结构: struct Vector { public int X, Y; // ... // some other stuff } 还有一节课: class Map { public Vector this[int i] { get { return elements[i]; } set { elements[i]

假设我有一个结构:

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
}
  • 将向量定义为类, 或
  • 将值存储在临时变量中

    var v=映射[索引]; v、 X=0; map[索引]=v

  • 添加要更改的函数 map[index]=map[index].Offset()

  • 让[]运算符返回一个setter类

    类设置器{Vector[]Data;int索引;公共双X{get{return Data[Index];}set{Data[Index]=new Vector(value,Data[Index].Y);}}

    公共设置器此[int i] { 得到 { 返回新的Setter(){Data=elements,Index=i}; } }


编译器阻止您执行此操作,因为索引器返回的是对象的副本,而不是引用(结构按值传递)。索引器返回一个副本,您修改了这个副本,您根本看不到任何结果。编译器帮助您避免这种情况


如果你想处理这种情况,你应该使用类来代替,或者改变你处理向量的方式。您不应该修改它的值,而应该在构造函数中初始化它的值,更多关于这个主题:。

尽管泛型类在很多方面都工作得很好,但它们并没有提供任何通过引用访问结构的合理方法。这是不幸的,因为在许多情况下,结构集合比类对象集合提供更好的性能(减少内存占用和改进缓存位置)和更清晰的语义。当使用结构数组时,可以使用类似于
ArrayOfRectangle[5]的语句
效果非常明显:它将更新
数组矩形[5]
的字段
X
,但不会影响
矩形
类型的任何其他存储位置的字段
X
。唯一需要知道的是,
ArrayOfRectangle
是一个
Rectangle[]
Rectangle
是一个带有公共
int
字段
X
的结构。如果
Rectangle
是一个类,并且
ArrayOfRectangle[5]
中保存的实例曾经暴露于外部世界,则很难或不可能确定
ArrayOfRectangle[5]引用的实例是否存在
也被其他一些代码持有,这些代码希望其实例的字段
X
不会改变。使用结构时可避免此类问题

考虑到.net集合的实现方式,最好的方法通常是制作一个结构的副本,修改它,然后将其存储回去。这样做有点麻烦,但对于不太大的结构,通过使用值类型实现的内存占用和缓存局部性的改进可能会超过从数据结构显式复制对象和向数据结构显式复制对象的额外代码。与使用不可变类类型相比,这几乎肯定是一个重大的胜利

顺便说一句,我希望看到的是集合公开如下方法:
OperateOnElement(int-index,ref-T-element,ref-paramType-param,ActionByRef-proc)
将调用
proc
,其中包含集合的适当元素以及传入的参数。在许多情况下,可以调用这样的例程,而无需创建闭包;如果这样的模式被标准化,编译器甚至可以使用它很好地自动生成字段更新代码。

由于使用的是
struct
,所以会出现这种错误。那么…你确定要使用结构吗?(一般来说,答案通常是“否”)那么,我应该改用类吗?如果答案是“是”,那么还有另一个“这不是不可变的吗?”问题…@Nolonar,结构有很多“gotchas”(特别是可变结构)。如果我是你,我会使用
,直到我有充分的理由不这样做。当你使用struct时,每次都会复制数据。因此,除非保留副本,否则修改副本是没有意义的。所以你可以说:
varv=map[index];v、 X=0;map[索引]=vv
是内部数组的副本。修改副本后,需要将其分配回
map
Vector
可以作为不可变结构有效。注释“如果要使其不可变,请改为使其成为类”是有史以来最糟糕的建议之一。如果有一个struct数组,则可以轻松更改一个元素的一个字段,而不会影响任何其他元素中的该字段:
MyPointArray[4]。X+=3。如果有其他类型的集合,则比较困难,但也不太糟糕:
var Temp=MyPointList[4];温度X+=3;MyPointList[4]=温度。如果你有一个数组或你的可变向量类的列表,你怎么能安全地对它进行类似的修改呢?有时候有很好的理由来构建struct,它唯一公开的变异方法是通过整个struct复制;除此之外,如果有必要用不可变类替换结构,那么如果结构仅通过整个结构复制进行变异,这样的更改将更容易。不可变类和不可变结构都是体面的“单记录”持有者;在某些情况下,两者都可能略优于另一种。如果不需要嵌套的可变类,可变结构可以成为优秀的单记录持有者。可变类通常不是好的……单个记录持有者,因为可变类类型的每个存储位置都有效地保存了两条逻辑信息:它所引用的类对象的内容