是什么使用"参考"供参考型的变量在C#?
-
12-09-2019 - |
题
我的理解是,如果我通过一个值型(int
, struct
, 等)。 作为一个参数(而不 ref
关键词),一个副本可传递给方法,但是如果我用的 ref
关键字的一个参考,可变通过,不是一个新的一个。
但是,参照类型的,喜欢的类,即使没有 ref
关键词、参考的通过该方法,不是一个副本。所以有什么用的 ref
关键词参考-类型?
采取例如:
var x = new Foo();
之间的区别是什么下面?
void Bar(Foo y) {
y.Name = "2";
}
和
void Bar(ref Foo y) {
y.Name = "2";
}
解决方案
您可以改变什么foo
点使用y
:
Foo foo = new Foo("1");
void Bar(ref Foo y)
{
y = new Foo("2");
}
Bar(ref foo);
// foo.Name == "2"
其他提示
有要修改的实际参考的情况下,而不是指向的对象:
void Swap<T>(ref T x, ref T y) {
T t = x;
x = y;
y = t;
}
var test = new[] { "0", "1" };
Swap(ref test[0], ref test[1]);
乔恩斯基特写有关参数传入C#很大文章。它清楚地详细说明的确切行为和由值来传递参数,通过参考(ref
)的使用,以及通过输出(out
)。
下面是从页面ref
的重要参数报价有关:
参考参数没有通过 在使用的变量的值 函数成员调用 - 他们使用 变量本身。而不是 创建一个新的存储位置 在功能部件的可变 报关,同样的存储位置 被使用,所以变量的值 在功能部件和值 参考参数总会 是相同的。参考参数需要 裁判改性剂的两个部分 声明和调用 - 即 意味着它总是很清楚,当你 通过引用传递的东西。
非常漂亮解释这里: http://msdn.microsoft.com/en-us/library/s6938f28.aspx
从文章摘要:
引用类型不直接包含其数据的变量;它 包含它的数据的引用。当你通过引用类型 由值参数,能够改变指向的数据 基准,例如一个类的成员的值。但是,您 不能改变参考本身的值;也就是说,你不能 使用相同的参考为一类新的分配内存,并将它 坚持外块。要做到这一点,利用传递参数 ref或out关键字。
在通过与ref关键字的引用类型,则通过引用传递的参考,并在调用方法可以分配一个新值参数。这种变化会传播到呼叫范围。而不REF,参考通过值传递,并不会发生这种情况。
C#也具有“出”关键字这是很多像REF,不同之处在于用“REF”,参数必须在调用方法之前被初始化,并与“出”您必须分配在接收方法的值。
它允许修改所述参考中通过。e.g。
void Bar()
{
var y = new Foo();
Baz(ref y);
}
void Baz(ref Foo y)
{
y.Name = "2";
// Overwrite the reference
y = new Foo();
}
您也可以使用退出如果你不关心传递的参考:
void Bar()
{
var y = new Foo();
Baz(out y);
}
void Baz(out Foo y)
{
// Return a new reference
y = new Foo();
}
的代码的另一束
class O
{
public int prop = 0;
}
class Program
{
static void Main(string[] args)
{
O o1 = new O();
o1.prop = 1;
O o2 = new O();
o2.prop = 2;
o1modifier(o1);
o2modifier(ref o2);
Console.WriteLine("1 : " + o1.prop.ToString());
Console.WriteLine("2 : " + o2.prop.ToString());
Console.ReadLine();
}
static void o1modifier(O o)
{
o = new O();
o.prop = 3;
}
static void o2modifier(ref O o)
{
o = new O();
o.prop = 4;
}
}
在除了现有的答案:
如你要求的2种方法的区别是:使用ref
或out
时,没有CO(NTRA)方差:
class Foo { }
class FooBar : Foo { }
static void Bar(Foo foo) { }
static void Bar(ref Foo foo) { foo = new Foo(); }
void Main()
{
Foo foo = null;
Bar(foo); // OK
Bar(ref foo); // OK
FooBar fooBar = null;
Bar(fooBar); // OK (covariance)
Bar(ref fooBar); // compile time error
}
一个参数的方法似乎总是通过复制,该问题是一个复制的是什么。一个复制是通过一个复制构造的对象和由于所有变量对象在C#我相信是这种情况为所有的人。变量(目的)都喜欢的人生活在某一地址。我们要么改变人民生活在这些地址,或者我们可以创造更多引用的人生活在这些地址的电话簿(使浅份)。因此,超过一个标识符,可以参考同一地址。参考类渴望更多的空间,所以不像值类型的直接连通过一个箭头对他们的标识符叠,他们具有价值,另一个地址在堆(一个更大的空间来纠缠).这个空间的需要采取从堆。
值类型:标识符(包含值=的地址堆值)---->值价值的类型
参照类型:标识符(包含值=的地址堆值)---->(包含值=的地址堆值)---->堆值(最经常含有地址的其他价值观),设想更多的箭坚持在不同的方向,以Array[0],Array[1],array[2]
唯一的方法要改变的一个值是按照箭。如果一个箭头丢失/改变的方式的价值是不可到达。
参考变量进行从一个地方到另一个地方的地址,以便在任何地方对他们的任何更新用将反映在所有的地方又是什么用REF的。 直到没有新的存储器被分配给在该方法中经过参考变量参考变量(405)是好的。
在新的存储器分配(410),那么该对象(408)上的值改变将不会到处反映。 对于这个裁判来。裁判的参考基准所以每当新的内存分配它搞懂,因为它指向一个位置,因此该值可以由大家共享。你可以看到该图像获得更多clearity。