我有一些有趣的东西,我想要深入了解。
我有一个扩展类扩展为int:
public static class MyExtension
{
public static void GetProp(this int i, MyObject o)
{
var val = i;
o.sum = i;
}
}
它使用一个类作为其参数之一:
public class MyObject
{
public int sum { get; set; }
}
现在,让我们看一下单元测试类:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void test()
{
int a = 1;
int b = 2;
int sum = 0;
Add(a, b, sum);
//这里,sum = 3但是在执行之后,sum会失去它的值和 保留值sum = 0
int test = 4;
MyObject obj = new MyObject();
test.GetProp(obj);
但是在上面的代码中我使用扩展名传递变量 方法,obj.sum保留其值 obj.sum = 4 。我没有通过任何 以参考价值。代码的第一部分似乎遵循 通过ByVal。但扩展方法的第二部分,值 保留,就像它作为ByRef
传递一样
string s = sum.ToString();
string p = obj.sum.ToString();
}
private void Add(int x, int y, int sum)
{
sum = x + y;
}
}
有人可以解释这背后的机制。感谢
答案 0 :(得分:3)
所有参数均按值发送,除非您使用ref
或out
关键字指定它们。按值传递参数意味着复制该值。
但是,当您按值传递对象时,它不是复制的对象,而是复制的引用。这意味着您有两个对同一对象的引用,一个在obj
变量中,另一个在o
参数中,但只有一个对象。
当扩展方法访问对象时,它与方法外部的对象相同。当您稍后使用o
变量访问该属性时,使用obj
参数对该属性所做的任何更改都将显示。
答案 1 :(得分:2)
这是传递引用和传递引用对象(class
)之间的区别。在GetProp
中,您无法修改引用obj
,而是修改MyObject
引用的obj
实例。
答案 2 :(得分:0)
如果我理解您的问题,您会感到困惑,为什么sum
变量在按值传递时没有更改,但是obj.sum
属性在{{1}时确实保留了其值}通过引用传递。其他答案很好地解释了这一点。
在您的问题中,您通过值作为接收者传递了一个参数,这使您的问题有些困惑。您的问题似乎是,“为什么当我正常通过时,将其视为按值,但是当我将其作为接收器传递给扩展方法时,将其作为按引用吗?”
啊。尝试为接收方分配一个新值,看看呼叫现场会发生什么:
obj
您会发现呼叫站点的变量 public static void GetProp(this int i, MyObject o)
{
o.sum = i;
i = 5000;
}
不受此影响,因为还通过值传递了接收者!