29

I've used lambda expressions in other languages before using them in C#, and so I got in the habit of using _ for simple lambdas in the form of Func<T, TResult>, especially for simple lambdas where the body is just an expression representing the return value (predicates, etc..). However, in C# I often see single letters being used instead of _ for these same sorts of lambda expressions, such as x,y,z,i,j,k. The letter approach seems odd to me since those letters already have another typical meaning in common usage, for loop variables. _ is often easier to read in my opinion. Is the single letter style really the established style for lambdas in C#?

Examples:

what I'm used to writing:

var ages = people.Select(_ => _.Age);

What I'm seeing being written instead:

var ages = people.Select(x => x.Age); // choice of 'x' is not consistent
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Jeremy Bell
  • 5,253
  • 5
  • 41
  • 63
  • 24
    I have never seen an underscore being used. – Ash Burlaczenko May 10 '12 at 17:05
  • Personally I use `w` for the lambda parameter when it's trivial to understand what I'm talking about. Remnant of http://research.microsoft.com/en-us/um/cambridge/projects/comega/ – Blindy May 10 '12 at 17:08
  • 1
    That's just people who are in love with terse, personally I use a meaningful name. neither x nor _ are meaningful. age would have been my choice in your example. – Tony Hopkinson May 10 '12 at 17:08
  • 8
    Age doesn't make sense to me, IMHO. "p" would've been my choice as it should be representing one "p"erson in the people collection. To each their own, though. :) – CodeHxr May 10 '12 at 17:31
  • 1
    @Tony there's a general consensus that when the scope is small enough, single-letter identifiers are just fine – Konrad Rudolph May 10 '12 at 19:39
  • _ looks Haskell-ish, I prefer ()=> – Lukasz Madon May 10 '12 at 20:23
  • Closely related threads [here](https://stackoverflow.com/q/41085189/465053) and [here](https://stackoverflow.com/q/18300654/465053) – RBT Sep 15 '17 at 02:15
  • My biggest aversion to _ in a lambda is using the shift key back and forth: shift-underscore, no-shift =, shift >, shift-underscore, dot. The pain is real. – secretwep Aug 20 '20 at 21:02

7 Answers7

55

Many C# developers use _ to indicate that the parameter isn't going to be used and a letter or other short name when the parameter is being used.

Other resources:

sblom
  • 26,911
  • 4
  • 71
  • 95
  • 1
    upvote for the Charlie Flowers article that explains the advent of legitimate _ usage. – Tetsujin no Oni May 10 '12 at 17:17
  • 1
    My examples were not quite right (I should have used p or person in those examples). At first I thought it might only apply to cases where the type of _ was generic/unknown, but in all cases where _ is used, at least something must be known about the type unless you're using methods on Object (in which case you'd use obj or similar), so that justification doesn't fly. This clears things up a bit. – Jeremy Bell May 10 '12 at 17:27
  • never considered using `_` for unused params. now i probably will everywhere.. – Jake Berger May 10 '12 at 19:31
  • 3
    This is consistent with many functional languages, where `_` is a "wlidcard pattern" that matches everything but does not bind the name, e.g. in Haskell `case 2 of x -> x` is `2`, but `case 2 of _ -> _` is a syntax error. – sdcvvc May 19 '12 at 17:13
  • As of C# 7, `_` is now formally used as part of discard patterns, similarly to how it's used in functional languages. This reinforces the case sblom makes. – Tagc Sep 16 '17 at 11:40
  • SSRS render calls come to mind: `reportViewer.ServerReport.Render(exportType == null ? "PDF" : exportType.ToString(), deviceInfo, out _, out _, out _, out _, out _);` ... yes, you can use it multiple times in one line of code without conflicts! – Riegardt Steyn Sep 18 '20 at 08:46
25

It's a variable name, so I'd go with the idea that the name should convey information that it needs to convey. What information does _ convey?

To that same end, what information does x convey?

I might write your example as this:

var ages = people.Select(p => p.Age);

The idea is that I feel that the p at least suggests in the context of the entire statement that it's a people record. You could take it even further:

var ages = people.Select(person => person.Age);

Now that conveys to the reader what that variable actually is. Of course, for such a small statement, an argument can be made that it's overkill. I don't think so, but it's a matter of preference. (And not just your preference, but the preference of anybody who has to support this code.)

For significantly larger, multi-line, complex lambda expressions, the name becomes even more important. The further away one is from the context of what the variable means, the more the name of the variable needs to carry that context with it.

David
  • 208,112
  • 36
  • 198
  • 279
  • 6
    Of course, the discarded-parameter case (say, for an anonymous event handler) where you are writing (_,__)=>{notificationEventHandler();} is the one where I continue to see (and support) the use of underscore-only names. – Tetsujin no Oni May 10 '12 at 17:19
  • 2
    @TetsujinnoOni: Of course. In that case, the variable is a non-variable. The only information it needs to convey is "I'm nothing, don't use me." – David May 10 '12 at 17:21
  • I second the use of `_ => _.method()` for one-line, method-call lambdas, since it reduces the instruction's cognitive weight. Specially when using generics, writing `x => x.method()` just adds that split-second consideration of "What's this 'x'? Is it a coordinate in space?". Consider the following case: `Initialize ( _=>_.Init() );` Used with Generics, the underscore in this case works as a "bypass symbol". It avoids redundancy, defining that the type of the argument is obvious and can be infered from usage - just as when using 'var' to prevent repeating a type declaration. – MaDDoX Jan 23 '17 at 13:15
17

How is a lambda function so different from any other method. If someone were to post code with a method such as:

public static int getAge(Person _)
{
  return _.Age;
}

or

public static int getAge(Person x)
{
  return x.Age;
}

What would you say?

In my opinion choosing the name of a parameter for a lambda should be just as meaningful as the parameter of any other method. I might make occasional exceptions for an identity function x => x because in that case the variable doesn't need to mean anything, it really can be anything, but using an underscore or a single letter for everything in my mind just makes the code that much less readable. (So many people tout the advantages of LINQ/Lambdas as being readability, which is defeated if you obfuscate all variables.)

Servy
  • 202,030
  • 26
  • 332
  • 449
  • 2
    Upvote for good perspective shift – hspain May 10 '12 at 17:49
  • @TetsujinnoOni if you saw someone write a method `public int getAge(Person p){return p.Age;}` what would you say? I know if I saw someone write that I'd say "you should use a more meaningful variable and not an abbreviation." I see no reason why the same logic doesn't apply equally to a lambda. – Servy May 10 '12 at 18:18
  • 1
    For simple predicates, the contention is that a meaningful variable name obfuscates what's happening. In both cases that you have written, the formalism of the method definition increases the amount of noise from which the signal must be differentiated, so the cost of naming the variable is increased. – Tetsujin no Oni May 10 '12 at 18:49
  • 6
    For a method that short, I would totally say that P was meaningful enough. the formalization is noise. – Tetsujin no Oni May 10 '12 at 18:49
  • Using meaningful variable names makes code more self-documenting. Rather than making it more difficult for the reader to look at `p => p.Age` and figure out that `p` is a person, or requiring comments to explain a terse LINQ expression I find that intelligent variable names makes the expression read just like the description of what it does. "from each person in people select the person's age" reads much nicer than "from each p in people select p's age". – Servy May 10 '12 at 19:00
  • 2
    What is different – scope and size of course. After all, that's the reason for the *existence* of lambdas. And that's reason enough to modify convention. – Konrad Rudolph May 10 '12 at 19:42
5

Or you could use a meaningful name, e.g.

var ages = people.Select(person => person.Age);
Danny Varod
  • 17,324
  • 5
  • 69
  • 111
2

In C#, _ is used for class(attribute) variables and _ is not used for local variables. So it is good to use meaningful name for local variables and class variable.

Ex:

var personList = (from person in people  where person.Age > 18  select person).ToList();
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
stay_hungry
  • 1,448
  • 1
  • 14
  • 21
0

There is no 'established' style for naming your lambda variables. However, an underscore typically means some kind of instance member variable, which means your style might conflict with other naming standards compared to a normal variable name.

Long Story Short - Do what works for you.

Tejs
  • 40,736
  • 10
  • 68
  • 86
0

There's a reason why you can give it a name -- because sometimes you can have multiple inputs and need to differentiate them:

Func<int,int,int> product = (num1, num2) => (num1 * num2);  // takes in two ints, and returns one int
int x = product(2, 3);  
BeemerGuy
  • 8,139
  • 2
  • 35
  • 46
  • True, but I don't think that is what the question was about. – Andrew Barber May 10 '12 at 17:22
  • Then you can be a real badass! (_,__) => (_*__); EDIT: k, SO naturally took my underscores as italic markers. Just showing to use double-underscores (or more) for multiple inputs. – Chris Sinclair May 10 '12 at 17:41
  • 1
    @ChrisSinclair, if you put backticks around your expression those special characters will be displayed as-is. – user May 11 '12 at 07:40
  • @MichaelKjörling yeah, I realized that a couple hours later and felt like a `socially awkward penguin`. – Chris Sinclair May 11 '12 at 12:35