2016-11-04 93 views
1

我明白规则。但谁知道这是为什么?为什么我无法将索引器作为ref参数传递?

如果我的代码是:

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]); 

裁判X [Y]只是一个指针,我感兴趣的T实例,不是吗?

为什么我不能以非常简单的方式编写代码行称为M1()。

我知道了解决方法:

T cX = x[y]; 
M1(ref cX); 

我希望听到的,为什么C#的建筑师需要这个额外的步骤来传递一个指针?还是它是一个编译器限制?

+1

'ref'和'out'适用于位置,而不是值。 'x [y]'是类型'T'的值,但'cX'是包含'T'的位置。 – Lee

+0

有一个[很多问题](http://stackoverflow.com/questions/529782/c-sharp-property-and-ref-parameter-why-no-sugar)已经有关于此。看看这个链接的第二个答案。 – Jonesopolis

回答

3

索引器值未被分类为变量;因此,您无法将索引器值作为ref或out参数传递。

参考msdn

+0

谢谢。我会接受这篇文章指出,索引器比我想象的要复杂得多。但是我也会在未来的c#编译器中发布这个构造约束消失。它更复杂,同时它非常简单。 – Steve

1

ref x[y]只是一个指向我的兴趣T实例是不是?

那么,如果T是一个引用类型,那么是的。如果T是一个值类型,那么不,但没关系,让我们暂时假设它是。由于该方法为ref T,因此需要接受对指向T实例的指针的变量的引用。你只需要一个指针,而不是一个存储位置的指针。 (请注意,我在你的比喻中,从技术上讲,你没有“指针”,你有一个对象的参考,但是这个比喻对于这个问题来说已经足够了)。列表的索引器没有解析为给定值的存储位置,它只解析为一个值。另外请注意,当你写:

T cX = x[y]; 
M1(ref cX); 

你不是反映cX任何突变回列表。你需要写:

T cX = x[y]; 
M1(ref cX); 
x[y] = cX; 

它实际上相当于以确保M1任何突变的变量 CX反映在列表中。

+0

那么为什么当我修改cX属性的值是从M1()返回后在x [y]中保留的修改? – Steve

+1

@Steve由于您正在修改引用所引用的值,因此您不会改变引用本身。如果这就是所有情况,那么方法不应该首先通过引用传递参数,因为它实际上并不会改变参考。 (请注意,通过引用传递参数应该是非常罕见的;对于通常的方法来说很少是合适的设计。) – Servy

+0

另外一个指针是一个内存地址,它包含的值是包含一个值的内存地址出于兴趣。我将对象的引用看作包含该对象实例地址的内存地址。对我来说似乎很相似。除语言外,你如何看待它? – Steve

相关问题