扩展方法的变量作用域

本文关键字:作用域 变量 方法 扩展 | 更新日期: 2023-09-27 18:05:50

我有一件有趣的事,我想更深入地了解一下。

我有一个扩展类扩展了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);

但是在上面的代码中,当我使用扩展传递变量时方法,即对象。sum保留其值obj。sum = 4。我什么都不传引用值。代码的第一部分似乎跟在通过值传递。但是扩展方法的第二部分,值就像传递ByRef

一样保留
            string s = sum.ToString();
            string p = obj.sum.ToString();
        }
        private void Add(int x, int y, int sum)
        {
            sum = x + y;
        }
    }
有人能解释一下这背后的机制吗?由于

扩展方法的变量作用域

所有参数都是按值发送的,除非您使用refout关键字指定它们。按值传递参数意味着复制该值。

然而,当你按值传递一个对象时,被复制的不是对象,而是引用。这意味着您对同一个对象有两个引用,一个在obj变量中,一个在o参数中,但只有一个对象。

当扩展方法访问对象时,它是与方法外部相同的对象。当您稍后使用obj变量访问该属性时,使用o参数对其所做的任何更改都是可见的。

这是通过引用传递和传递引用对象(class)之间的区别。在GetProp中,您没有修改引用obj,您正在修改由obj引用的MyObject实例。

如果我理解你的问题,你对为什么sum变量在按值传递时不改变感到困惑,但是当obj通过引用传递时,obj.sum属性确实保留其值。其他答案很好地解释了这一点。

在您的问题中,您通过值传递参数作为接收器,这使您的问题有点混乱。你的问题似乎是,"为什么当我正常传递时,它被视为按值处理,但当我作为接收者传递给扩展方法时,它是按引用处理?"

啊。试着给接收者赋一个新值,看看调用现场会发生什么:

    public static void GetProp(this int i, MyObject o)
    {
        o.sum = i;
        i = 5000;
    }

您将发现调用站点的变量test不受此影响,因为接收者也是按值传递的 !