Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Operators as method parameters in C#

I don't think it's possible to use operators as a parameters to methods in C# 3.0 but is there a way to emulate that or some syntactic sugar that makes it seem like that's what's going on?

I ask because I recently implemented the thrush combinator in C# but while translating Raganwald's Ruby example

(1..100).select(&:odd?).inject(&:+).into { |x| x * x }

Which reads "Take the numbers from 1 to 100, keep the odd ones, take the sum of those, and then answer the square of that number."

I fell short on the Symbol#to_proc stuff. That's the &: in the select(&:odd?) and the inject(&:+) above.

like image 450
Jonas Elfström Avatar asked Oct 06 '09 21:10

Jonas Elfström


People also ask

Can we pass operator as argument?

You can't directly. You need to pass in a representation of the operator (commonly using an enum) and the function then translates that to the right operator.

What are parameters in c programming?

The parameter in C refers to any declaration of variables within the parenthesis during the function declaration. These are listed in the function's definition, separated by commas. Example of Parameter. int add (int a, int b) { int c = a + b; return c; } In the above lines of code, we can see the function definition.

Can you pass an operator as a parameter C++?

You can overload operators and pass them to functions. It just so happens that this cannot be done (for no good reasons) with pre-defined operators of built-in types.

What does it mean to take *& as a parameter?

It means a reference to a pointer to an int. In other words, the function can change the parameter to point to something else. To pass a variable in, just pass an int*. As awoodland points out, what's passed in must be an l-value.


2 Answers

Well, in simple terms you can just use a lambda:

public void DoSomething(Func<int, int, int> op)
{
    Console.WriteLine(op(5, 2));
}

DoSomething((x, y) => x + y);
DoSomething((x, y) => x * y);
// etc

That's not very exciting though. It would be nice to have all those delegates prebuilt for us. Of course you could do this with a static class:

public static class Operator<T>
{
     public static readonly Func<T, T, T> Plus;
     public static readonly Func<T, T, T> Minus;
     // etc

     static Operator()
     {
         // Build the delegates using expression trees, probably
     }
}

Indeed, Marc Gravell has done something very similar in MiscUtil, if you want to look. You could then call:

DoSomething(Operator<int>.Plus);

It's not exactly pretty, but it's the closest that's supported at the moment, I believe.

I'm afraid I really don't understand the Ruby stuff, so I can't comment on that...

like image 156
Jon Skeet Avatar answered Sep 20 '22 07:09

Jon Skeet


The following is direct, literal (as much as possible) C# translation:

(Func<int>)(x => x * x)(
    Enumerable.Range(1, 100)
        .Where(x => x % 2 == 1)
        .Aggregate((x, y) => x + y))

Specifically:

  • blocks: {||} - become lambdas: =>
  • select becomes Where
  • inject becomes Aggregate
  • into becomes a direct call on a lambda instance
like image 20
Pavel Minaev Avatar answered Sep 20 '22 07:09

Pavel Minaev