19

At various times while programming in C# I've found myself in situations where I'd like to define a lambda (or anonymous delegate) and call it in the same line. At this point, the 'cleanest' way I've been able to do this is like this:

bool foo_equals_bar = new Func<String, bool>(str => str.Equals("foo"))("bar");

I would love to be able to do write something like the following instead:

bool foo_equals_bar = (str => str.Equals("foo"))("bar");

Unfortunately, this doesn't seem to work. I would love to know:

  1. Is there a simpler way of writing the line of code above?
  2. What is returned from (str => str.Equals("foo")) such that is can be used to initialize a Func<String, bool>, but can not be evaluated like a Func<String, bool>?

I should point out that I'm working in C# 3 (VS2008), so if a solution only exists in C# 4, please mention that. (I'd still like to know, even if the solution isn't available to me at the moment).

Thanks

Shane Arney
  • 4,314
  • 3
  • 22
  • 17
  • 3
    How is this different than just `"bar".Equals("foo")`? I understand it's likely simplified, but I'm not seeing a situation where you wouldn't be able to do make the same translation. – Joel Coehoorn Jan 21 '11 at 17:07
  • 1
    I'm not trying to find a clever way to compare strings, it's just a simplified example to demonstrate principles (and, unfortunately, incorrect syntax) – Shane Arney Jan 21 '11 at 23:14

6 Answers6

15

You would need a set of helper methods to make compiler infer lambda types, e.g.:


public static class Functional
{
    public static Func<TResult> Lambda<TResult>(Func<TResult> func)
    {
        return func;
    }

    public static Func<T, TResult> Lambda<T, TResult>(Func<T, TResult> func)
    {
        return func;
    }

    public static Func<T1, T2, TResult> Lambda<T1, T2, TResult>(Func<T1, T2, TResult> func)
    {
        return func;
    }
}

Now you can write:


bool foo_equals_bar = Functional.Lambda(str => str.Equals("foo"))("bar");

Konstantin Oznobihin
  • 5,234
  • 24
  • 31
  • Cool idea. It's essentially syntactic sugar for create a Func<> type and letting the compiler infer the types. – Shane Arney Jan 21 '11 at 18:24
  • very very cool. way underrated. May you receive many upvotes for this. Also, guessing from the name you chose for this class, do you have more nifty tricks to make functional programming in C# more convenient? – sehe Apr 08 '11 at 08:29
  • 2
    @sehe: well, this trick is rather widely known, but thanks anyways. As for other tricks, probably, the most useful one now is called F# :) it's far better than emulating such things like curried functions, point-free style, pattern matching and ADT in C#. One more little thing I use in C# is a convertor from Action delegates to Func, which is easily done by making a lambda returning Object or a special Unit type. – Konstantin Oznobihin Apr 08 '11 at 18:42
  • At least on my LINQPad/C# 7, your example doesn't work - it can't infer the type of `str`. – NetMage Jun 12 '18 at 21:36
  • I had the same error as @NetMage. I had to declare the type of str: `bool foo_equals_bar = Functional.Lambda((string str) => str.Equals("foo"))("bar");` – kristianp Apr 10 '19 at 23:43
  • There is nothing about `Equals` that allows the compiler to infer a type for `str`. – NetMage Apr 11 '19 at 16:00
8
str => str == "A" 

is the same as

delegate (string str) { return str == "A";};

So no, there's no way to get just the lambda, since the compiler wouldn't know what type str is if you just said

bool result = (str => str == "A")("B");

EDIT:

Yes, you can add types to lambda expressions, like (string str) => str == "A"; but still, they can't be implicit for some reason. Not sure why. Thanks for the comment, Yuriy.

om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
  • 1
    In his code thats true. But the issue is you can't have an implicit lambda expression. You could still use `(string str) => str.Equals("foo")` and the compiler would know what type str is. – Yuriy Faktorovich Jan 21 '11 at 17:04
  • 2
    There is no problem for compiler in knowing what type str is, the problem is in inferring delegate type, because delegates with the same signatures are still of different types in .NET. – Konstantin Oznobihin Jan 21 '11 at 17:33
  • 1
    Thanks Konstantin - yeah, it's obvious now that you mention it. ie Func is the same as Predicate, so the compiler couldn't know when you meant with (string s) => s == "A" – Adam Rackis Jan 21 '11 at 18:36
  • I think the edit is a bit misleading, as the lambda `(string str) => str == "A";` cannot be assigned to a "simple" variable (like `bool` or `var`), but to something like `Func` (for reference, here's [Eric Lippert's explanation](https://stackoverflow.com/a/4966409/3002584)). – OfirD Jul 14 '20 at 14:02
8

What is returned from (str => str.Equals("foo")) such that is can be used to initialize a Func, but can not be evaluated like a Func?

Just using built-in types, there's:

Expression<Func<string, bool>> a = str => str.Equals("foo");
Expression<Predicate<string>> b = str => str.Equals("foo");
Expression<Action<string>> c = str => str.Equals("foo");
Func<string, bool> a1 = str => str.Equals("foo");
Predicate<string> b1 = str => str.Equals("foo");
Action<string> c1 = str => str.Equals("foo");

All of which are valid interpretations of the lambda expression. That's just the built-in types that I can think of off the top of my head. There's also any delegate that matches the signature.

Davy8
  • 30,868
  • 25
  • 115
  • 173
5

At various times while programming in C# I've found myself in situations where I'd like to define a lambda (or anonymous delegate) and call it in the same line.

Those are strange situations. Avoid them. This is not possible because the compiler cannot infer the type. This could work when you pass the anonymous delegate to some method from which the compiler can infer the types.

And in any cases:

bool foo_equals_bar = "bar".Equals("foo");

is far more readable than*:

bool foo_equals_bar = (str => str.Equals("foo"))("bar");

* assuming such syntax was possible

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Yeah, as pointed out in the comment to my answer, there's no reason the compiler shouldn't be able to figure out: bool result = ((string str) => str == "A")("B"); - I don't know why that's not supported, but as Darian said, that wouldn't be very readable anyway. – Adam Rackis Jan 21 '11 at 17:09
  • 1
    Actually, compiler do can infer types, see my answer about how to make it do this. It can't infer type without such helpers because there is no such thing as universal function type in .NET, i.e. it can equally be Func and delegate bool MyCoolDelegateType(string str) and compiler can't prefer one of them. – Konstantin Oznobihin Jan 21 '11 at 17:24
  • 2
    Of course the first line is more readable than the second - if all I needed was a simple equals comparison I wouldn't both with the lambda. The code was just a bare-bones example of what I was asking. – Shane Arney Jan 21 '11 at 18:28
1

You have to cast the lambda to a func or delegate
((Func<string, bool>)(str => str.Equals("bar")))("baz")

Michael DiLeo
  • 571
  • 1
  • 4
  • 15
-2
using System.Threading.Tasks;
using System.Threading;

Task.Run(()=>{
     //do something
});

You can add a 500ms delay with

Task.Run(()=>{
    Thread.Sleep(500);
    //do something
});

Not sure when MS added it but it wasn't C#3

this programming style can accomplish anything and you can basically ignore the rest of C# specs once you learn this