eca*_*ver 11 c# reference reference-type
众所周知,C#classes对象被视为引用,那么当您将引用对象作为对方法的引用传递时会发生什么?说我们有:
public class A { ... }
Run Code Online (Sandbox Code Playgroud)
然后:
public void F(ref A a) { ... }
Run Code Online (Sandbox Code Playgroud)
编译器是否发现它a已经是一个引用类型并保持这种方式,或者他创建了一个对该对象的新引用?
如果我们有这样的事情怎么办:
public void F(ref A a)
{
F(ref a);
}
Run Code Online (Sandbox Code Playgroud)
在这段代码中,除了显而易见之外StackOverflowException,编译器是否创建了对引用的引用...以引用a哪个是引用对象?
Eri*_*ert 27
最好用一个例子来说明:
public class C { public int P { get; set; } }
public class X
{
static void M(C c1, C c2, ref C c3, ref C c4)
{
c1.P = 11;
c2 = new C() { P = 12 };
c3.P = 13;
c4 = new C() { P = 14 };
}
static void Main()
{
C q1 = new C() { P = 1 };
C q2 = new C() { P = 2 };
C q3 = new C() { P = 3 };
C q4 = new C() { P = 4 };
M(q1, q2, ref q3, ref q4);
Console.WriteLine(q1.P);
Console.WriteLine(q2.P);
Console.WriteLine(q3.P);
Console.WriteLine(q4.P);
}
}
Run Code Online (Sandbox Code Playgroud)
怎么了?
q1和c1指的是同一个对象,但它们是不同的变量.变异c1.P会改变q1.P,因为两个变量都引用同一个对象,所以q1现在是11.
q2和c2指的是同一个对象,但它们是不同的变量.突变c2不会突变q2,因为c2和q2是不同的变量; 换一个不会改变另一个.q2保持2,新对象丢失.
q3和c3是同一个变量的两个名称,因此引用同一个对象.当您更改自动更改q3.P的c3.P时,因为它们是同一个事物的两个名称.
q4和c4是同一变量的两个名称,因此变异q4也会使c4发生变异.
那有意义吗?
不幸的是,"为这个变量做一个别名"的关键字是"ref".如果它是"别名",那就更清楚了.
回答你的第二个问题:不,这不是一个引用链.让我们做一个更清晰的例子:
...
int c1 = 123;
M(ref c1);
...
void M1(ref int q1) { M2(ref q1); }
void M2(ref int q2) { M2(ref q2); }
Run Code Online (Sandbox Code Playgroud)
这表示c1和q1是同一变量的不同名称,q1和q2是同一变量的不同名称,因此c1,q1和q2都是彼此的别名.在C#中,C#中没有"引用变量"的引用.
在像这样的通话中
F(ref a); // ByRef parameter
Run Code Online (Sandbox Code Playgroud)
该变量a由 method 的主体“直接使用” F。只有一个存储位置。如果该方法F分配给它的参数,则该分配将a立即对每个可以看到的人可见。相反,如果有人(外部)在方法运行时F分配给,那么 的参数将“突然”更改为新对象。aFF
另一方面,在像这样的通话中
F(a); // normal value parameter
Run Code Online (Sandbox Code Playgroud)
首先将变量a复制到新变量,然后在内部使用新变量F。现在,如果 的参数类型F是值类型(如struct或enum),则通过 value完成复制。所以整个数据都被复制了。但如果参数的类型是引用类型((包括数组类型)、、),则 的副本仅涉及引用的副本。classinterfacedelegatea
要检查您对带有类型参数的值参数情况的理解class,请弄清楚这些方法的作用:
static void F1(List<int> list>) // no ref modifier
{
list.Clear();
}
static void F2(List<int> list>) // no ref modifier
{
list = new List<int>();
}
Run Code Online (Sandbox Code Playgroud)
这是一些可能有趣的例子ref:
static void G(ref string a, ref string b)
{
if (string.Equals(a, b))
b += "_unique";
// Is it now safe to say that a and b are distinct?
// No. Anyone could have changed either a or b by now.
// For example, a and b could "alias" public fields visisble to other threads.
}
Run Code Online (Sandbox Code Playgroud)
作为上述使用的示例,请考虑以下情况下的G代码将与方法内部一起更改。var x = "initial"; G(ref x, ref x);abG