1
\$\begingroup\$

Currently I'm saving the values, gotten from a method, to a variable and using them later on.

This is the example code of how I do it:

var events = class.GetEvents();

if(events.Length > 0)
{
     foreach(var event in events)
     {
        // do something
     }
}       
else
{
     // No events
     Console.Log("No Events");
}

But actually, What I'd like to achieve is something more like this:

foreach(var event in class.GetEvents()) // <-- If none, I'd like to know.
{
      // do something
} 

However, I still need to log that there weren't any results. I'd have to do a check, and re-call the method to see if there are any results.. OR i++ in my loop, and if that's a 0 => log.

Is there a simpler way to do this?

\$\endgroup\$

closed as off-topic by 200_success Nov 30 '17 at 15:48

This question appears to be off-topic. The users who voted to close gave this specific reason:

If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    \$\begingroup\$ I proposed this exact thing on the C# language. There's no built-in, intuitive way to do it except how you currently do. \$\endgroup\$ – Der Kommissar Nov 30 '17 at 14:44
  • 3
    \$\begingroup\$ Quick example what you can do with an extension method is a ForEach method and call it with the loop statement and an else statement like this: class.GetEvents().ForEach((event) => { /* loop block */ }, () => { /* else statement */ }); \$\endgroup\$ – xander Nov 30 '17 at 14:55
  • 1
    \$\begingroup\$ What's bad in using variables? \$\endgroup\$ – Rango Nov 30 '17 at 15:18
  • 1
    \$\begingroup\$ I am sorry about your experience with this question being closed, but we prioritize preventing invalidation of answers very highly here. You mentioned in your edit that you included the changes from Tim's answer. Tim reviewed your first edition already, posting another edition of code would be confusing when some answers review different editions. \$\endgroup\$ – Simon Forsberg Nov 30 '17 at 17:33
  • 2
    \$\begingroup\$ @Paramone What you should do if you want this question reopened is to use your own, un-edited code, yes. We have had several occurrences on this site of users replying to answers with something like "That's not useful to me because that's not applicable to my real code", which is one of the reasons for putting a question like this on hold exists. We believe that it makes things easier for everyone if we can see the real code, instead of seeing code that has been edited for the purpose of showing it to others. If you want to discuss this more just let me know and I will move discussion to chat. \$\endgroup\$ – Simon Forsberg Nov 30 '17 at 17:43
2
\$\begingroup\$

I don't understand why you don't want to use a variable. However, one way is to provide an extension method for this:

public static void ForEachDo<T>(this IEnumerable<T> seq, Action<T> doWithEveryItem, Action doIfEmpty = null)
{
    bool isEmpty = true;
    foreach (T item in seq)
    {
        isEmpty = false;
        doWithEveryItem(item);
    }
    if (isEmpty && doIfEmpty != null)
        doIfEmpty();
}

Now you can use it with everything that implements IEnumerable<T> like a string:

"".ForEachDo(Console.WriteLine, () => Console.WriteLine("No Events")); // prints "No Events"
\$\endgroup\$
  • \$\begingroup\$ Perfect! I want my code to be easily readable, functioning and somewhat complex and 'versatile'. I think this is the best answer in terms of my liking. Using variables are obviously not wrong, but I think it looks way better this way. \$\endgroup\$ – Paramone Nov 30 '17 at 15:38
  • \$\begingroup\$ Just one more thing, instead of that bool variable you could also use if (!seq.Any() && doIfEmpty != null) { doIfEmpty(); return; } at the top and after that the foreach. INumerable<T>.Any() should be the same as INumerable<T>.Length > 0 :) \$\endgroup\$ – xander Nov 30 '17 at 15:41
  • 1
    \$\begingroup\$ @xander: please don't do that. Enumerable.Any will check if there's any item. But seq could also be a database query which needs an hour to execute. This innocent Any would need to execute it completely(if there is no record matching) to evaluate that there is none. After this you are going to enumerate the query again. \$\endgroup\$ – Rango Nov 30 '17 at 15:57
0
\$\begingroup\$

You can use Debug.WriteIf method for this.

public void Method() 
{
    var events = class.GetEvents();
    Debug.WriteIf(events.Length > 0, "No Events");

    foreach(var event in events)
    {
        // do something
    } 
}

You can check it's documentation here.

Of course this will be executed only in Debug configuration and will output to Output window, but you can easily borrow the idea for your logger and do the same logic.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.