41

The () seems silly. is there a better way?

For example:

ExternalId.IfNotNullDo(() => ExternalId = ExternalId.Trim());

DaveShaw
  • 52,123
  • 16
  • 112
  • 141
brendanjerwin
  • 1,381
  • 2
  • 11
  • 25

4 Answers4

44

Sort of! There is a new idiom in town, that is nice and may help you in some cases. It is not fully what you want, but sometimes I think you will like it.

Since underscore ("_") is a valid C# identifier, it is becoming a common idiom to use it as a parameter name to a lambda in cases where you plan to ignore the parameter anyway. If other coders are aware of the idiom, they will know immediately that the parameter is irrelevant.

For example:

ExternalId.IfNotNullDo( _ => ExternalId=ExternalId.Trim());

Easy to type, conveys your intent, and easier on the eyes as well.

Of course, if you're passing your lambda to something that expects an expression tree, this may not work, because now you're passing a one-parameter lambda instead of a no-parameter lambda.

But for many cases, it is a nice solution.

MyDaftQuestions
  • 4,487
  • 17
  • 63
  • 120
Charlie Flowers
  • 17,338
  • 10
  • 71
  • 88
  • 47
    I really don't see how this is better than (). Swapping slightly ugly syntax for slightly ugly pseudo-syntax doesn't seem like a win. – Greg Beech Mar 25 '09 at 08:35
  • 5
    Well, you're definitely welcome to your opinion. It is a subjective matter. But to me it greatly reduces visual clutter, is easier to read, and is easier to type. The original question was motivated by a dislike of the () syntax, so this presents an alternative. – Charlie Flowers Mar 25 '09 at 09:28
  • Awesome! This is what I was after. Not Quite as ugly and at least it's an option. – brendanjerwin Mar 25 '09 at 11:08
  • 4
    In F#, _ is a matchall pattern, so it's nice having similarity when having to use C#. Many of my event handlers look like "foo += (_,__) ...". – MichaelGG Mar 29 '09 at 20:51
  • 7
    A one-parameter lambda is a priest, a two-parameter lambda is a beast. But I will bet a striped pajama, you've never seen a three-parameter lambda. – Dan J Nov 16 '10 at 17:33
  • 1
    You can't embed lambda functions using this method. For example, `RelayCommand(_ => { task.ContinueWith(_ => { // do stuff } }` won't work due to a collision on the underscore. But, you may be using too many lambda's at that point ;) – Pakman Feb 18 '11 at 22:53
  • 4
    I have to agree with @Greg; it doesn't look any better than `()`. Besides, it doesn't answer the question as the underscore approach won't work for parameterless lambdas. If I plan to ignore the parameters, I *ignore* the parameters by using a `delegate { ... }` (see Mark's answer). – Niels van der Rest Jul 05 '11 at 15:31
  • 1
    @Niels van der Rest -- odd that you say it doesn't answer the question, when the OP said, "Awesome! This is what I was after." The question was, can I have something prettier to write and read when I don't care about parameters. The answer was this. You're caught up in semantics. – Charlie Flowers Jul 05 '11 at 17:01
  • 2
    @CharlieFlowers: It really *doesn't* answer the question though, regardless of the OP's reaction. Is your lambda expression parameterless, as asked in the question? No. Your code *cannot* be used for a delegate which has no parameters. – Jon Skeet May 27 '13 at 08:26
  • 1
    @Jon Skeet, you're acting like a compiler instead of a human. What the OP meant (as indicated by his response), was, "I need to use lambdas a lot in cases where I don't care about parameters, but I hate the syntax." Otherwise, he would not have been so enthusiastic about this option. (Also, please note that my first words were "Sort of", and I later added, "It's not fully what you want.") So this answer provides an alternative that doesn't work for *every* case you need a parameterless lambda, but it does work for those cases where you truly *don't care* about the parameters. – Charlie Flowers May 27 '13 at 18:01
  • 1
    @CharlieFlowers: It works for cases where you don't care about the parameter, but there is one. (And using an anonymous method works well for that case too.) I find that I rarely get to decide which delegate type I'll use though - and I certainly wouldn't choose to use a delegate which *does* take a parameter which I know I'll then ignore, just to be able to use `_` instead of `()`. In the case where the OP really *doesn't* have any parameters - including the example given in the question - this answer doesn't help at all. I wouldn't like to claim to know why the OP was enthusiastic about this – Jon Skeet May 27 '13 at 19:09
  • 1
    (In particular, your comment about expression trees seems to imply that it's *only* a problem if you're using expression trees, not just regular delegates. That's not the case. Your approach won't work if your method accepts a plain `Action` or `Func`, for example.) – Jon Skeet May 27 '13 at 19:10
  • I can think of 2 cases where you could use this. Case one, where you're in control of the code that calls the lambda, and case two, where you know the lambda will be called with one parameter, but you don't care about it. In the first case, you'd call the lambda with a dummy parameter simply to make the _=> "idiom" possible. And I'll grant you, that would be somewhat "unorthodox". But some people will be unorthodox to get what they feel leads to "pretty" code. I'm not surprised that you would vote against it, and I'd probably lean against it too, but if someone wanted to use it in a – Charlie Flowers May 27 '13 at 22:31
  • ... unit test DSL or something, I wouldn't stress too much over it. Now, for the second case, where you know the lambda will be called with one parameter, the underscore "idiom" is not bad at all. It all comes down to this -- often the first response to the ()=> syntax is "yuck" (as you alluded to in your response). And as all the other answers show, there really is not *much* of an alternative. But there is this one *tiny* alternative that might help *sometimes*. And this tiny alternative is *creative*, out-of-the-box, which leads to an appreciation for it in spite of its limitations. – Charlie Flowers May 27 '13 at 22:35
  • Oh, by the way, since I'm praising its creativeness, I should add that I didn't invent this. I wish I could remember where I heard about it, but I don't (it was 4 years ago after all:) ) – Charlie Flowers May 27 '13 at 22:38
  • Stackoverflow popped up a message that I should avoid extended discussions and offered me a link to "automatically move this discussion to chat." I clicked the link, but I'm OK with the conversation being here or there. – Charlie Flowers May 27 '13 at 22:57
  • 2
    I'm fine with this pattern when there *is* a parameter. I'm just saying that it doesn't answer the question that was asked, which was about a lambda expression which *doesn't* have a parameter. The correct answer to the question that was actually asked was, "No, there's no other way of writing a parameterless lambda expression." (I didn't downvote this answer, by the way - it's not that I think it's actively unhelpful, I just don't think it answers the question the OP asked. If the OP was actually trying to ask something else, well, that's a different matter..) – Jon Skeet May 28 '13 at 05:26
  • I see where you're coming from. I would say there is a small overlap between the question and the answer. And that is the first case I referred to. If you are building your own framework or DSL, and you hate the ()=> syntax so much that you're willing to really stretch to get around it, you could use _=> for all your parameterless lambdas, but remember to write the code that calls the lambda such that it passes a dummy parameter. True, it doesn't answer the literal question, I acknowledge that. And it's not often that all those "planets align." So it's not terribly practical. It's more like... – Charlie Flowers May 28 '13 at 06:31
  • ... a loophole that should be mentioned for the sake of completeness. But in one sense, ironically, I can defend it from an "overly literal" point of view. The OP asked if there was an alternative, and the answer is, "yes, but only when an unusual set of circumstances align, and even then it's unorthodox, but here it is." – Charlie Flowers May 28 '13 at 06:35
  • 1
    Let me retract the "acting like a compiler instead of a human" statement. I thought, at first, that you were intentionally being overly literal. I see where you're coming from more now. Indeed, one could argue that *I* must resort to being overly literal at this point :) – Charlie Flowers May 28 '13 at 06:40
  • 2
    For developers familiar with Scala, using the underscore (`_`) may be confusing/misleading; my company develops in botch C# and Scala. In Scala, you can use the `_` character to replace, one-time-use variables in a lambda expression. For instance `(x, y) => x + y` can be replaced with `_ + _`. For this reason, I don't really like using the `_` for this purpose. [Here is more info](http://stackoverflow.com/questions/7673545/usage-of-in-scala-lambda-functions) on Scala's usage of `_`. – Jesse Webb Jan 09 '14 at 17:56
  • That lambda is not a parameterless method. It does not work for ThreadStart for example. – Mose Apr 08 '14 at 09:18
  • 1
    I agree with @NielsvanderRest; if I'm planning on ignoring the parameter, I almost always use `delegate { }` instead. However, there are some cases where there is a difference between `() => { blah }` and `delegate { blah }`. For a full explanation, see this answer: http://stackoverflow.com/questions/299703/delegate-keyword-vs-lambda-notation – lfalin Mar 26 '15 at 16:35
26

For a lambda, no: you need () =>

Is it for a delegate or an expression? For delegates, another option is delegate {...}. This may or may not be desirable, depending on the scenario. It is more keys, certainly...

In some cases (not this one) you can use a target method directly - i.e.

ExternalId.IfNotNullDo(SomeMethod);
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
19

No, there isn't. Lambda expressions are optimised (in terms of syntax) for the single parameter case.

I know that the C# team feels your pain, and have tried to find an alternative. Whether there ever will be one or not is a different matter.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 10
    @aateeque: I don't think it answers the question at all. It gives an idea of how to write a lambda expression with one parameter that you plan to ignore, but that's not the same as a parameterless lambda. – Jon Skeet May 27 '13 at 08:25
-1

Essentially what you're looking for is the inverse of the ?? null coalescing operator (which is called Nullable<T>.GetValueOrDefault() under the covers) - problem is C# doesn't provide a neat OOTB answer.

Don't know exactly what you're doing but as you are doing:

ExternalId.IfNotNullDo(()=>ExternalId=ExternalId.Trim());

you might also find a use for:

class NullExtensions
{
    public T DefaultOr<T>( this T that, Func<T> transform)
    {
        return that!=default(T) ? transform(that) : default(T);
    }
}

which would enable:

var result = input.DefaultOr( _ => _.Trim());

(in general, I'd be trying to steer away from reusing / mutating variables as you seem to be doing and instead going in an Introduce Explaining Variable / Split Temporary Variable direction i.e., use a new variable rather than value = value.DefaultOr( _ => _.Trim());)

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249