我查看了类似的问题并阅读了一些文章。 THis文章中有一些图片说清楚。
SomeObject so = new SomeObject();
somefunction(so);
Console.write(so.x); // will print 1
SomeObject so1 = new SomeObject();
somefunctionByRef(so1);
Console.write(so1.x); // will print 1
static void somefunction(SomeObject so)
{
so.x = 1;
}
public void somefunctionByRef(ref SomeObject so)
{
so.x = 1;
}
这两种方法对此引用类型具有相同的效果。那么为什么选择ref
关键字作为参考类型?
使用somefunction(SomeObject so)并修改方法中的对象并期望更改而不使用ref关键字是不好的做法(可能是假的)?
答案 0 :(得分:3)
传入.Net的默认参数是按值完成的。对于值类型和引用类型都是如此。不同之处在于,对于引用类型,您将通过值与实际对象传递对实例的引用。
效果是原始函数中的so
引用,someFunction是独立的。更改引用引用的实例对另一个实例没有影响。但是因为它们引用相同的对象,所以可以看到另一个对象完成的对象的突变(这就是为什么x在你的例子中发生了变化)
SomeObject so = new SomeObject();
so.x = 42;
somefunction(so);
Console.Write(so.x); // will print 42
static void somefunction(SomeObject so) {
so = new SomeObject();
so.x = 13;
}
ref
修饰符导致参数通过引用而不是值传递。实际上没有引用的副本,原始函数和调用函数中的so
是相同的引用。所以重置一个重置另一个
SomeObject so = new SomeObject();
so.x = 42;
somefunction(ref so);
Console.Write(so.x); // will print 13
static void somefunction(ref SomeObject so) {
so = new SomeObject();
so.x = 13;
}
答案 1 :(得分:1)
我在处理非引用类型时只使用ref,例如int,decimal等。
看看this MSDN page以获得更清晰的解释,以及一些问题
答案 2 :(得分:1)
类已经通过引用传递(在非托管术语中,因此是指向对象的指针)。传递引用可以更改基础变量(您正在使用指向指针的指针)。拿这个代码:
static void foo(SomeObject so)
{
so.x = 1;
so = null;
}
static void bar(ref SomeObject so)
{
so.x = 1;
so = null;
}
SomeObject so1 = new SomeObject();
foo(so1);
Console.write(so1.x); // will print 1
bar(so1);
Console.write(so1.x); // crash
第一种方法将起作用,你将打印出1 - 指定为null只是更改函数本地的变量。第二个将导致崩溃(NullReferenceException),因为so1已设置为null。
答案 3 :(得分:0)
对于引用类型,默认情况下,参数通过引用传递,除非指定通过值传递。我认为这是一个足够安全的假设,大多数.Net开发者都应该知道。