23

In JavaScript, it's not uncommon to see self-invoking functions:

var i = (function(x) {
    return x;
})(42);

// i == 42

While I'm certainly not comparing the languages, I figured such a construct would be translatable to C#, provided a language version with support:

var i = (delegate(int x) {
    return x;
})(42);

Or:

var i = ((x) => {
    return x;
})(42);

Or even:

var i = (x => x)(42);

However, every version is in error:

Method name expected

Are self-invoking anonymous methods unsupported (due either to explicit forbiddance, or the impossibility of type inference), or is there an error in my attempts?

I'm venturing a guess that because there was no method declaration (Func<T,T>) against which the types could be inferred, it can't sort out the implied types, figures I meant to call a declared method by name, and really goofed up the syntax.


Errata

Before this question is flooded with:

var i = new Func<int, int>(x => x)(42);

I should say that I was hoping to leverage type inference, but I suppose that may not be possible due to being overly-implicit.

So, clarifying the question a bit; we know we can var i = new Func<int, int>(x => x)(42); but without creating an instance of, or casting to Func, is this possible?

Use-Case

For those curious (or concerned) the use case was something like this:

var o = new {
    PropertyA = () => {
        // value computation
    }(),
    PropertyB = () => {
        // value computation
    }(),
};
Dan Lugg
  • 20,192
  • 19
  • 110
  • 174
  • 1
    Consider why you need this construct in javascript, and apply that concept to c#. – asawyer Mar 07 '13 at 18:31
  • @asawyer While I appreciate the "teach a man to fish" approach to your comment, a little elaboration would be appreciated ;) – Dan Lugg Mar 07 '13 at 18:32
  • 1
    What exactly does a self invoked function accomplish in javascript? – asawyer Mar 07 '13 at 18:33
  • http://stackoverflow.com/questions/1208703/can-an-anonymous-method-in-c-sharp-call-itself – d.moncada Mar 07 '13 at 18:33
  • AFAIK the only **true and reasonable** case you may _think_ to use self-invoking methods is [this](http://stackoverflow.com/questions/9612019/using-self-calling-anonymous-functions-and-document-ready). Any use-case in C#? – Adriano Repetti Mar 07 '13 at 18:36
  • @asawyer it allows you to create a private closure that contains private variables only accessible by the object you return from the function. Code consuming the returned function cannot get to those private variables. See [this question](http://stackoverflow.com/questions/5647258/how-to-use-revealing-module-pattern-in-javascript) – Brandon Mar 07 '13 at 18:39
  • @asawyer Sorry (*between many things*), what Brandon said; additionally, for the sake of brevity which is what I was going for. – Dan Lugg Mar 07 '13 at 18:41
  • 1
    @Brandon The point, I guess, is if it's a good thing to do or not. If you write a _long_ anonymous function maybe your code will be more clear if you write a _true_ named function. – Adriano Repetti Mar 07 '13 at 18:49
  • @Bracketworks about your "errata": C# is typed... – Adriano Repetti Mar 07 '13 at 18:50
  • @Adriano Of course; is the typing simply too implicit to infer from? I certainly agree with you point on creating a named method if the procedure is long enough to warrant one; I was trying to use very short methods so it *should* have been applicable. – Dan Lugg Mar 07 '13 at 18:52
  • 1
    @Bracketworks So you need an object that can contain private variable values, that can expose properties and other functions? I think there is a word for this type of construct in c#... – asawyer Mar 07 '13 at 18:54
  • @asawyer Funny guy. No, I was trying to leverage the brevity of anonymous methods and fluent interfaces for a specific use-case. I don't need to protect or expose any data; I was after a brief way to inline statements where they would otherwise be syntactically erroneous. – Dan Lugg Mar 07 '13 at 18:56
  • @Bracketworks Why play syntax tricks when the language gives you the feature for free? Consider code maintenance. What do you think Bracketworks(+5 years) is going to think about your tricks when trying to track down some subtle bug? – asawyer Mar 07 '13 at 18:59
  • @asawyer I'm completely for readability, and human parse-ability. I appreciate your concern. I highly doubt this use-case would have been any more or less difficult to understand than the alternatives; merely shorter. – Dan Lugg Mar 07 '13 at 19:02
  • @Bracketworks I didn't catch the point you're playing with the syntax, in this case what's better or readable is pretty irrelevant. I posted an answer about it. – Adriano Repetti Mar 08 '13 at 08:55

3 Answers3

20
var x = ((Func<int, int>)(y => y * 2))(10);

The problem is that when the compiler sees y => y * 2 it classifies it as an Expression instead of a Func by default, unless there is some contextual information to let it know it should be a Func. By casting it to Func we give it the context it needs.

Brandon
  • 38,310
  • 8
  • 82
  • 87
  • 5
    `var i = new Func(x => x)(42);` syntax is also valid. – Caramiriel Mar 07 '13 at 18:34
  • 1
    @Caramiriel: ah yeah I've never considered using the constructor syntax :) – Brandon Mar 07 '13 at 18:36
  • If that is indeed the case; that the compiler sees `x => x` and interprets it as an expression, then why wouldn't the `delegate` alternative work? (*or is that too assumed to be an expression?*) – Dan Lugg Mar 07 '13 at 18:44
  • 1
    @Bracketworks: I believe it is because an anonymous method declared with `delegate` is not fully typed until it is assigned to something. Again it needs context. This works: `((Func)delegate(int y) { return y * 2; })(10);`. See [MSDN](http://msdn.microsoft.com/en-us/library/0yw3tz5k.aspx) – Brandon Mar 07 '13 at 18:56
11

I suppose someone from the C# team can give a much better answer but I try my shot. Question here is not if it's a best practice or not but if it's possible and, if not, why.

Let's start with what you would write:

var i = (x => x)(42);

Pretty straightforward, you pass an integer (42) to a lambda, it plays with it and it returns the same value. Its parameter is an integer (inferred from its usage), it returns an integer (inferred from the expression) and i is another integer (inferred from return value).

Unfortunately this is broken in the very first step. Let me cite big Jon:

Compiler tries to work out the types of the parameters for lambda expressions based on the context in which it's used.

What does it mean? Actually that the compiler need some information but it can use only:

  • An explicit cast, constructor or declaration like in (Func<int, int>)(x => x)) or new Func<int, int>(x => x). Required types here are given or inferred using the required final type.
  • An assignment (again because the final type can be inferred) like in: Func<int, int> f = (x => x);

In your case the compiler have to infer function type from its parameters and it's not possible because parameters are validated against the expression and not vice-versa.

Why this is not possible in C#? Because (x => x) is just a delegate then it can be any delegate that accept an integer parameter (if we suppose the compiler can infer lhs from rhs and validate rhs according to lhs) and returns another integer. Actually conversion between delegates are not allowed in C# so the expression is invalid (even if this special delegate won't be assigned to any variable and it won't be used in the future). It could be Func<int, int> or Expression<Func<int, int>> or any other delegate (for bool parameter it may even bee Predicate<bool>).

Of course this is a C# design decision, the same expression - for example - in VB.NET is perfectly valid:

 Dim i = (Function(x) x)(42)

Different language, different rules to obey, C# goal is to avoid this kind of ambiguity.

Community
  • 1
  • 1
Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
1

I worked around the language limitation using overloaded static method that accepts an anonymous function and executes it:

namespace Utils {
    public static class InvokeInlineHelper {
        public static T Invoke<T>(Func<T> f) {
            return f();
        }

        public static T Invoke<A1, T>(Func<A1, T> f, A1 a1) {
            return f(a1);
        }

        //...overloads with more than 1 argument
    }
}

The usage is quite simple and it maintains type-safety. This is my Program.cs file:

global using static Utils.InvokeInlineHelper;

const string prefix = "Value";

var o = new
{
    PropertyA = Invoke(() => {
        return prefix + "A";
    }),
    PropertyB = Invoke((input) => {
        return prefix + input;
    }, "B"),
};

Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(o));
//Outputs: {"PropertyA":"ValueA","PropertyB":"ValueB"}

Note the global static using which improves the syntax. Closures can be still leveraged, of course, as demonstrated with prefix variable.

matej bobaly
  • 456
  • 3
  • 6