Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement call by name in C#?

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

like image 272
Dr TJ Avatar asked Oct 25 '10 21:10

Dr TJ


2 Answers

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.

like image 70
Ron Warholic Avatar answered Oct 01 '22 01:10

Ron Warholic


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;
}
like image 22
Jeremy Thompson Avatar answered Oct 01 '22 02:10

Jeremy Thompson