扩展方法的可变范围

问题描述 投票:0回答:3

我有一些有趣的东西,我想更深入地了解。

我有一个扩展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失去其值,并且保留值总和= 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;
        }
    }

有人可以解释其背后的机制。谢谢

c# scope extension-methods
3个回答
3
投票

所有参数均按值发送,除非您使用refout关键字指定它们。通过值传递参数意味着该值已被复制。

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

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


2
投票

这是通过引用传递和传递参考对象(class)之间的差异。在GetProp中,您不是在修改引用obj,而是在修改MyObject引用的obj实例。


0
投票

[如果我理解您的问题,您会感到困惑,为什么sum变量在通过值传递时没有更改,但是obj.sum属性在通过引用传递obj时仍保留其值。其他答案很好地解释了这一点。

在您的问题中,您按值作为接收者]传递了一个参数,这使您的问题有些困惑。您的问题似乎是:“为什么当我正常通过时,将其视为按值,但是当我作为接收器传递给扩展方法时,将其作为按引用吗?”

啊尝试为接收方分配一个新值,并查看呼叫现场发生的情况:

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

您会发现呼叫站点的变量test不受此影响,因为

通过值传递了接收者!
© www.soinside.com 2019 - 2024. All rights reserved.