DannyD
DannyD

Reputation: 2881

How to use linq to return a boolean

I have a foreach loop where I'm iterating through a list to make sure every item is valid and want to return a boolean.

Here's my foreach code:

bool isValid = true;

foreach (var req in requestList)
{
    if (!req.ChannelId.HasValue || !req.PayoutAmountInCents.HasValue)
    {
        isValid = false;
        PayoutFDEvents.LogInvalidPayoutRequest(this.BuildPayoutFDDocument(req), "missing channelId or patronage amount");
    }
}   

and here's my attempt to convert it to a linq statement:

var isValid = requestList
    .Select(r =>
    {
        if (!r.ChannelId.HasValue || !r.PayoutAmountInCents.HasValue)
        {
            PayoutFDEvents.LogInvalidPayoutRequest(this.BuildPayoutFDDocument(r), "missing channelId or patronage amount");
            return false;
        }
        return true;
    });

However, looks like my implementation returns a list of bools instead. Is there a way I can return an overall bool?

Upvotes: 1

Views: 3094

Answers (3)

Hooman Bahreini
Hooman Bahreini

Reputation: 15559

You can also try this:

var invalids = requestList.Where(r => !(r.ChannelId.HasValue && r.PayoutAmountInCents.HasValue)).ToList();
invalids.ForEach(r => PayoutFDEvents.LogInvalidPayoutRequest(BuildPayoutFDDocument(r), "msg"));
bool isValid = invalids.Any();

I think your logic is too complex to be done in a one line statement.

Upvotes: 1

mjwills
mjwills

Reputation: 23898

One option would be to use:

var isValid = requestList
          .Select(r => 
          {
              var valid =r.ChannelId.HasValue && r.PayoutAmountInCents.HasValue;
              if (!valid)
              {
                  PayoutFDEvents.LogInvalidPayoutRequest(
                      this.BuildPayoutFDDocument(req), "missing channelId or patronage amount");
              }
              return valid;
          })
          .DefaultIfEmpty(true)
          .Min();

Because false is "less" than true, this will return false if any of the individual entries meet the condition (i.e. are null).

The DefaultIfEmpty bit is to handle the scenario where requestList is empty - in which case isValid will be set to true.

In all honesty though, since you are performing the logging inside your existing loop I would keep your existing code. It is simple, clear, and easy to read and understand.

Upvotes: -1

slugster
slugster

Reputation: 49984

This could be converted to a simple expression like this:

var isValid = requestList.All(r => r.ChannelId.HasValue && r.PayoutAmountInCents.HasValue)

I would suggest you don't log something in the middle of your expression - this is just smelly and won't work very well once you convert to using All()

Upvotes: 3

Related Questions