Extension method and local variable 'this'

As far as I know, this in the 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(); 

Now my List<int> ints 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 be 3, 4, 5 , but would remain untouched. Am I missing something?

+7
c # extension-methods ref local
source share
2 answers

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

+5
source share

Well, when you try to change the property of an instance of a class, you don’t even need to ref , because you are modifying the instance, not referring to it.

In this example, you do not need the ref keyword when changing the 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 need the ref keyword, because you are working with a link, not an 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

The same for your scenario, the extension methods are the same as regular static methods, and if you create a new object inside the method, you either use the ref keyword (this is not possible for extension methods) or return this object, otherwise the link will be lost.

So, in the 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

+3
source share

All Articles