Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doesn't C# Extension Methods allow passing parameters by reference?

Tags:

Is it really impossible to create an extension method in C# where the instance is passed as a reference?

Here’s a sample VB.NET console app:

Imports System.Runtime.CompilerServices  Module Module1   Sub Main()     Dim workDays As Weekdays      workDays.Add(Weekdays.Monday)     workDays.Add(Weekdays.Tuesday)      Console.WriteLine("Tuesday is a workday: {0}", _        CBool(workDays And Weekdays.Tuesday))     Console.ReadKey()   End Sub End Module  <Flags()> _ Public Enum Weekdays   Monday = 1   Tuesday = 2   Wednesday = 4   Thursday = 8   Friday = 16   Saturday = 32   Sunday = 64 End Enum  Module Ext   <Extension()> _   Public Sub Add(ByRef Value As Weekdays, ByVal Arg1 As Weekdays)      Value = Value + Arg1   End Sub End Module 

Note the Value parameter is passed ByRef.

And (almost) the same in C#:

using System;  namespace CS.Temp {   class Program   {     public static void Main()     {       Weekdays workDays = 0;        workDays.Add(Weekdays.Monday); // This won't work       workDays.Add(Weekdays.Tuesday);        // You have to use this syntax instead...       // workDays = workDays | Weekdays.Monday;       // workDays = workDays | Weekdays.Tuesday;        Console.WriteLine("Tuesday is a workday: {0}", _          System.Convert.ToBoolean(workDays & Weekdays.Tuesday));       Console.ReadKey();     }   }    [Flags()]   public enum Weekdays : int   {     Monday = 1,     Tuesday = 2,     Wednesday = 4,     Thursday = 8,     Friday = 16,     Saturday = 32,     Sunday = 64   }    public static class Ext   {     // Value cannot be passed by reference?      public static void Add(this Weekdays Value, Weekdays Arg1)      {       Value = Value | Arg1;     }   } } 

The Add extension method doesn’t work in C# because I can’t use the ref keyword. Is there any workaround for this?

like image 745
Jakob Gade Avatar asked Aug 11 '09 08:08

Jakob Gade


1 Answers

No. In C#, you cannot specify any modifiers (like 'out' or ref) other than this for the first parameter of an extension method - you can for the others. Not familiar with the VB Syntax but it seems to be using a declarative approach to mark an extension method.

When you call it, you do not specify the first this parameter. Hence marking the parameter as out or ref doesnt make sense as You can't specify the modifier when you call it like you'd do for normal methods

void MyInstanceMethod(ref SomeClass c, int data) { ... } // definition  obj.MyInstanceMethod(ref someClassObj, 10);              // call  void MyExtensionMethod(this SomeClass c, int data) {.... } // defn  c.MyExtensionMethod(10);                                 // call 

I think the trouble you're having here is related to value types being immutable. If Weekdays was a reference type, it would work out alright. For immutable types (structs), the defacto way is to return a new instance with the required value. E.g. See the Add method on the struct DateTime, it returns a new DateTime instance whose value = receiver DateTime instance's value + param value.

public DateTime Add( TimeSpan value ) 
like image 173
Gishu Avatar answered Sep 21 '22 09:09

Gishu