5

Can anyone tell me how I can implement Call By Name in C#?

Alexander Rossa
  • 1,900
  • 1
  • 22
  • 37
Dr TJ
  • 3,241
  • 2
  • 35
  • 51
  • What version of C# are you using (what is you Visual Studio version)? – Dirk Vollmar Oct 25 '10 at 22:01
  • A compiler in C#, who'd of thunk it! – Byron Whitlock Oct 25 '10 at 22:01
  • @0xA3: It doesn't matter, it should be like a compiler or something like that... – Dr TJ Oct 25 '10 at 22:04
  • @Dr TJ: How would that not matter when you ask about an *implementation*? Different versions of C# have different features available. – Dirk Vollmar Oct 25 '10 at 22:06
  • @0xA3: because this is just about algorithm and I can't use any compilers ability... Just i have to do implementations in one programming language – Dr TJ Oct 25 '10 at 22:09
  • 2
    @Dr TJ: Yes, and C# 4.0 is a different programming language than C# 2.0, complete with different, improved capabilities for handling precisely this issue. – Steven Sudit Oct 25 '10 at 22:53
  • Do you want to use C# as if it were a call-by-name language or do you want to implement a language that uses call-by-name in C#? The "compiler-theory" tag makes it look like the latter, but everyone seems to have answered the former. – sepp2k Oct 26 '10 at 10:33

5 Answers5

9

Pass a lambda function instead of a value. C# is eagerly evaluated so in order to defer execution so that each site re-evaluates the supplied arguments you need to wrap the arguments in a function.

int blah = 1;

void Foo(Func<int> somethingToDo)  {
  int result1 = somethingToDo(); // result1 = 100

  blah = 5;
  int result2 = somethingToDo(); // result = 500
}

Foo(() => blah * 100);

You can use the Lazy class if you're in .NET 4.0 to get a similar (but not identical) effect. Lazy memoizes the result so that repeated accesses do not have to re-evaluate the function.

Ron Warholic
  • 9,994
  • 31
  • 47
3
public enum CallType
{
/// <summary>
/// Gets a value from a property.
/// </summary>
Get,
/// <summary>
/// Sets a value into a property.
/// </summary>
Let,
/// <summary>
/// Invokes a method.
/// </summary>
Method,
/// <summary>
/// Sets a value into a property.
/// </summary>
Set
}

/// <summary>
/// Allows late bound invocation of
/// properties and methods.
/// </summary>
/// <param name="target">Object implementing the property or method.</param>
/// <param name="methodName">Name of the property or method.</param>
/// <param name="callType">Specifies how to invoke the property or method.</param>
/// <param name="args">List of arguments to pass to the method.</param>
/// <returns>The result of the property or method invocation.</returns>
public static object CallByName(object target, string methodName, CallType callType, params object[] args)
{
  switch (callType)
  {
    case CallType.Get:
      {
        PropertyInfo p = target.GetType().GetProperty(methodName);
        return p.GetValue(target, args);
      }
    case CallType.Let:
    case CallType.Set:
      {
        PropertyInfo p = target.GetType().GetProperty(methodName);
        p.SetValue(target, args[0], null);
        return null;
      }
    case CallType.Method:
      {
        MethodInfo m = target.GetType().GetMethod(methodName);
        return m.Invoke(target, args);
      }
  }
  return null;
}
Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
2

You can do that using Reflection:

using System;
using System.Reflection;

class CallMethodByName
{
   string name;

   CallMethodByName (string name)
   {
      this.name = name;
   }

   public void DisplayName()      // method to call by name
   {
      Console.WriteLine (name);   // prove we called it
   }

   static void Main()
   {
      // Instantiate this class
      CallMethodByName cmbn = new CallMethodByName ("CSO");

      // Get the desired method by name: DisplayName
      MethodInfo methodInfo = 
         typeof (CallMethodByName).GetMethod ("DisplayName");

      // Use the instance to call the method without arguments
      methodInfo.Invoke (cmbn, null);
   }
}
fresskoma
  • 25,481
  • 10
  • 85
  • 128
  • 5
    This is not call-by-name. http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_name – Ron Warholic Oct 25 '10 at 22:00
  • 5
    The OP most likely refers to http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_name which is different from dynamically calling a method based on the name. – Dirk Vollmar Oct 25 '10 at 22:03
  • Given they accepted this answer, I suspect the OP was actually referring to VB.NET's [CallByName](https://msdn.microsoft.com/en-us/library/microsoft.visualbasic.interaction.callbyname) – isedwards Jan 28 '18 at 14:39
1

Why not use

Microsoft.VisualBasic.Interaction.CallByName
antyrat
  • 27,479
  • 9
  • 75
  • 76
the bill
  • 29
  • 2
1

If you mean this, then I think the closest equivalent would be delegates.

Steven Sudit
  • 19,391
  • 1
  • 51
  • 53