Extension method and local 'this' variable

故事扮演 提交于 2021-02-08 13:32:57

问题


To my knowledge this in a extension method is passed as a ref variable. I can verify this by doing

public static void Method<T>(this List<T> list)
{
    list.Add(default(T));
}

List<int> ints = new List<int>(new int[] { 1, 2, 3, 4, 5 });
ints.Method();

My List<int> ints is now 1, 2, 3, 4, 5, 0.

However when I do

public static void Method<T>(this List<T> list, Func<T, bool> predicate)
{
    list = list.Where(predicate).ToList();
}

List<int> ints = new List<int>(new int[] { 1, 2, 3, 4, 5 });
ints.Method(i => i > 2);

I would expect my List<int> ints to be 3, 4, 5 but remains untouched. Am I missing something obvious?


回答1:


The this extension method parameter is passed by value, not by reference. What this means is that upon entering the extension method, you have two variables pointing to the same memory address: the original ints and the list parameter. When you add an item to the list inside the extension method, it is reflected in ints, because you modify an object referenced by both variables. When you reassign list, a new list is created on the managed heap and the extension method's parameter points to this list. The ints variable still points to the old list.




回答2:


Well, when you try to modify property of some class instance you don't even need ref because you're modifying instance rather then reference to it.

In this example you don't need ref keyword as you modify property :

    class MyClass
    {            
        public int MyProperty { get; set; }
    }

    static void Method(MyClass instance)
    {
        instance.MyProperty = 10;                     
    }

    static void Main(string[] args)
    {
        MyClass instance = new MyClass();
        Method(instance);

        Console.WriteLine(instance.MyProperty);
    }

Output : 10

And here you do need ref keyword because you work with reference and not with instance :

    ...

    static void Method(MyClass instance)
    {
        // instance variable holds reference to same object but it is different variable
        instance = new MyClass() { MyProperty = 10 };
    }

    static void Main(string[] args)
    {
        MyClass instance = new MyClass();
        Method(instance);

        Console.WriteLine(instance.MyProperty);
    }

Output: 0

It's same for your scenario, extension methods are the same as normal static methods and if you create new object inside method then either you use ref keyword (it's not possible for extension methods though) or return this object otherwise the reference to it will be lost.

So in your second case you should use :

public static List<T> Method<T>(this List<T> list, Func<T, bool> predicate)
{
    return list.Where(predicate).ToList();
}

List<int> ints = new List<int>(new int[] { 1, 2, 3, 4, 5 });
ints = ints.Method(i => i > 2);

foreach(int item in ints) Console.Write(item + " ");

Output : 3, 4, 5



来源:https://stackoverflow.com/questions/33056956/extension-method-and-local-this-variable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!