C# 为什么可以';我是否将索引器作为ref参数传递?
我理解规则。但谁知道这是为什么呢 如果我的代码是:C# 为什么可以';我是否将索引器作为ref参数传递?,c#,.net,C#,.net,我理解规则。但谁知道这是为什么呢 如果我的代码是: List<T> x = new List<T>; x.Add(new T()); x.Add(new T()); x.Add(new T()); int y = 2; //And I call a method M1(ref x[y]); 我希望听到为什么c#的架构师需要额外的步骤来传递指针?或者这是编译器的限制?索引器值未被归类为变量;因此,不能将索引器值作为ref或out参数传递 参考索引器值未分类为变量;因
List<T> x = new List<T>;
x.Add(new T());
x.Add(new T());
x.Add(new T());
int y = 2;
//And I call a method
M1(ref x[y]);
我希望听到为什么c#的架构师需要额外的步骤来传递指针?或者这是编译器的限制?索引器值未被归类为变量;因此,不能将索引器值作为ref或out参数传递
参考索引器值未分类为变量;因此,不能将索引器值作为ref或out参数传递 提及
ref x[y]
只是指向我感兴趣的T
实例的指针,不是吗
如果T
是一个引用类型,那么是的。如果T
是一种值类型,那么不是,但这并不重要,让我们暂时假设它是。由于该方法是ref T
,因此它需要接受对变量的引用,该变量是指向T
实例的指针。您只有一个指针,而不是指针的存储位置。(请注意,我只是停留在你的类比中。从技术上讲,你没有“指针”,你有一个对对象的引用,但就这个问题而言,这个类比已经足够好了。)
列表索引器的getter不会解析为给定值的存储位置,它只解析为一个值。还请注意,在编写时:
T cX = x[y];
M1(ref cX);
您没有将cX的任何突变反映回列表。你需要写:
T cX = x[y];
M1(ref cX);
x[y] = cX;
它实际上是等效的,以确保M1
中变量cX的任何突变都反映在列表中
ref x[y]
只是指向我感兴趣的T
实例的指针,不是吗
如果T
是一个引用类型,那么是的。如果T
是一种值类型,那么不是,但这并不重要,让我们暂时假设它是。由于该方法是ref T
,因此它需要接受对变量的引用,该变量是指向T
实例的指针。您只有一个指针,而不是指针的存储位置。(请注意,我只是停留在你的类比中。从技术上讲,你没有“指针”,你有一个对对象的引用,但就这个问题而言,这个类比已经足够好了。)
列表索引器的getter不会解析为给定值的存储位置,它只解析为一个值。还请注意,在编写时:
T cX = x[y];
M1(ref cX);
您没有将cX的任何突变反映回列表。你需要写:
T cX = x[y];
M1(ref cX);
x[y] = cX;
确保列表中反映了M1
中变量cX的任何突变。ref
和out
适用于位置,而不是值x[y]
是一个类型为T
的值,但cX
是一个包含T
的位置。关于这一点已经有了一个定义。查看该链接上的第二个答案。ref
和out
适用于位置,而不是值x[y]
是一个类型为T
的值,但cX
是一个包含T
的位置。关于这一点已经有了一个定义。请看链接上的第二个答案。谢谢。我承认这篇文章指出,索引器比我想象的要复杂得多。但我也会在未来的c#编译器版本中看到这种构造约束消失了。它更复杂,同时也很简单。谢谢。我承认这篇文章指出,索引器比我想象的要复杂得多。但我也会在未来的c#编译器版本中看到这种构造约束消失了。它更复杂,同时也很简单。那么,为什么当我修改cX属性的值时,修改会在从M1()返回后保留在x[y]中?@Steve因为您在修改引用引用的值,而不是修改引用本身。如果这就是所发生的一切,那么该方法首先不应该通过引用传递参数,因为它实际上并没有改变引用。(注意,通过引用传递参数应该是非常罕见的;对于一般的方法来说,这很少是合适的设计。)指针也是一个内存地址,其中包含一个值,该值是指向包含感兴趣的值的内存位置的地址。我将对对象的引用视为包含该对象实例地址的内存地址。对我来说似乎差不多。除了语言之外,你如何看待它呢?@Steve在C#中的引用并不是一个值的实际内存地址,而是运行时与该值关联的一个数字。它不一定是(可能是,但不一定是)实际的内存地址。这是相关的,因为C#是一种垃圾收集语言,因此值的物理内存地址将随着每次垃圾收集而不断移动,但对该值的C#引用是常量,即使物理位置移动,也会引用它。在处理实际指针时,这一区别也是相关的(C#在unsafe
code中支持哪一个),通常在使用其他语言(如C/C++)时,这些语言处理实际的物理内存地址。在这种情况下,C#引用和物理内存地址之间的差异非常重要。如果不这样做,这种差异在很大程度上是不相关的。那么为什么要修改cX属性的值呢从M1()返回后,修改是否在x[y]中持续存在?@Steve因为您正在变异引用引用的值,而不是变异引用本身。如果发生的只是这些,则该方法首先不应通过引用传递参数,因为它实际上没有变异引用。(注意,通过引用传递参数应该是非常罕见的;对于一般的方法来说,它很少是合适的设计。)指针也是内存地址