Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extension method and local 'this' variable

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?

like image 561
Arthur Rey Avatar asked Oct 10 '15 17:10

Arthur Rey


People also ask

What is extension method with example?

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are static methods, but they're called as if they were instance methods on the extended type.

What is extension method in Python?

The extend() method adds all the elements of an iterable (list, tuple, string etc.) to the end of the list.

What is extension method in OOP?

In object-oriented computer programming, an extension method is a method added to an object after the original object was compiled. The modified object is often a class, a prototype or a type. Extension methods are features of some object-oriented programming languages.

What is the difference between a static method and an extension method?

The only difference between a regular static method and an extension method is that the first parameter of the extension method specifies the type that it is going to operator on, preceded by the this keyword.


2 Answers

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.

like image 193
Kapol Avatar answered Oct 21 '22 05:10

Kapol


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

like image 43
Fabjan Avatar answered Oct 21 '22 07:10

Fabjan