Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.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# 为什么可以';我是否将索引器作为ref参数传递?_C#_.net - Fatal编程技术网

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因为您正在变异引用引用的值,而不是变异引用本身。如果发生的只是这些,则该方法首先不应通过引用传递参数,因为它实际上没有变异引用。(注意,通过引用传递参数应该是非常罕见的;对于一般的方法来说,它很少是合适的设计。)指针也是内存地址