I have the following Linq query:
result.Partials.Where(o => o.IsPositive).Min(o => o.Result)
I get an exception when result.Parti
You can use the DefaultIfEmpty method to ensure the collection has at least 1 item:
result.Partials.Where(o => o.IsPositive).Select(o => o.Result).DefaultIfEmpty().Min();
Min var min = result.Partials.Where(o => o.IsPositive).Min(o => o.Result);
This is your case: if there are no matching elements, then the Min call will raise an exception (InvalidOperationException).
DefaultIfEmpty() -- still troublesome var min = result.Partials.Where(o => o.IsPositive)
.Select(o => o.Result)
.DefaultIfEmpty()
.Min();
DefaultIfEmpty will create an enumeration over the 0 element, when there are no elements in the list. How do you know that 0 is the Min or if 0 stands for a list with no elements?
var min = result.Partials.Where(o => o.IsPositive)
.Min(o => (decimal?)o.Result);
Here Min is either null (because that's equal to default(decimal?)) or the actual Min found.
So a consumer of this result will know that:
null then the list had no elementsMin of those elements is that returned value.However, when this doesn't matter, then min.GetValueOrDefault(0) can be called.
You can't use Min (or Max) if the sequence is empty. If that shouldn't be happening, you have a different issue with how you define result. Otherwise, you should check if the sequence is empty and handle appropriately, eg:
var query = result.Partials.Where(o => o.IsPositve);
min = query.Any() ? query.Min(o => o.Result) : 0; // insert a different "default" value of your choice...
Yet another way to express it in LINQ is to use Aggregate:
var min = result.Partials
.Where(o => o.IsPositive)
.Select(o => o.Result)
.Aggregate(0, Math.Min); // Or any other value which should be returned for empty list
Since LINQ lacks methods like MinOrDefault() and MaxOrDefault(), you can create them by yourself:
public static class LinqExtensions
{
public static TProp MinOrDefault<TItem, TProp>(this IEnumerable<TItem> This, Func<TItem, TProp> selector)
{
if (This.Count() > 0)
{
return This.Min(selector);
}
else
{
return default(TProp);
}
}
}
Therefore, if the collection has values, the Min() is calculated, otherwise you get the property type's default value.
An example of use:
public class Model
{
public int Result { get; set; }
}
// ...
public void SomeMethod()
{
Console.WriteLine("Hello World");
var filledList = new List<Model>
{
new Model { Result = 10 },
new Model { Result = 9 },
};
var emptyList = new List<Model>();
var minFromFilledList = filledList.MinOrDefault(o => o.Result)); // 9
var minFromEmptyList = emptyList.MinOrDefault(o => o.Result)); // 0
}
NOTE 1: you don't need to check if the This parameter is null: the invoked Count() already checks that, and it throws the same Exception that you would throw.
NOTE 2: This solution is good only in situations where the Count() method is cheap to call. All .NET collections are fine since they are all very efficient; it could be a problem for particular customized/non-standard collections.