IEnumerable Extension - c#

I want to make an IEnumerable<TSource> extension that can convert itself to a IEnumerable<SelectListItem>. So far I have been trying to do it this way:
public static
IEnumerable<SelectListItem> ToSelectItemList<TSource, TKey>(this
IEnumerable<TSource> enumerable, Func<TSource, TKey> text,
Func<TSource, TKey> value)
{
List<SelectListItem> selectList = new List<SelectListItem>();
foreach (TSource model in enumerable)
selectList.Add(new SelectListItem() { Text = ?, Value = ?});
return selectList;
}
Is this the right way to go about doing it? If so how do I draw the values from the appropriate values from the Func<TSource, TKey> ?

You're re-inventing the wheel. It is what Enumerable.Select intended for.
EDIT BY #KeithS: To answer the question, if you want this output, you can define an extension method wrapping Enumerable.Select:
public static IEnumerable<SelectListItem> ToSelectItemList<TSource>(
this IEnumerable<TSource> enumerable,
Func<TSource, string> text,
Func<TSource, string> value)
{
return enumerable.Select(x=>new SelectListItem{Text=text(x), Value=value(x));
}

You just need to use the two functions you supply as parameters to extract the text and the value. Assuming both text and value are strings you don't need the TKey type parameter. And there is no need to create a list in the extension method. An iterator block using yield return is preferable and how similar extension methods in LINQ are built.
public static IEnumerable<SelectListItem> ToSelectItemList<TSource>(
this IEnumerable<TSource> enumerable,
Func<TSource, string> text,
Func<TSource, string> value)
{
foreach (TSource model in enumerable)
yield return new SelectListItem { Text = text(model), Value = value(model) };
}
You can use it like this (you need to supply the two lambdas):
var selectedItems = items.ToSelecListItem(x => ..., x => ...);
However, you could just as well use Enumerable.Select:
var selectedItems = items.Select(x => new SelectListItem { Text = ..., Value = ... });

You're on the right path.
Funcs are methods stored in variables, and are invoked like normal methods.
public static IEnumerable<SelectListItem> ToSelectItemList<TSource, TKey>(
this IEnumerable<TSource> enumerable,
Func<TSource, TKey> text,
Func<TSource, TKey> value)
{
List<SelectListItem> selectList = new List<SelectListItem>();
foreach (TSource model in enumerable)
{
selectList.Add(new SelectListItem()
{
Text = text(model),
Value = value(model)
});
}
return selectList;
}
If I might recommend, your Funcs should be Func<TSource, string> as the text and value are strings in the SelectListItem.
Edit Just thought of this...
Also you don't have to create an inner list but can do a yield return instead. Below is my "optimized" version of your method.
public static IEnumerable<SelectListItem> ToSelectItemList<TSource>(
this IEnumerable<TSource> enumerable,
Func<TSource, string> text,
Func<TSource, string> value)
{
foreach (TSource model in enumerable)
{
yield return new SelectListItem()
{
Text = text(model),
Value = value(model)
};
}
}
Here is the reference for yeild return. It allows you to return the your results as an element in an enumerable, constructing your enumerable invisibly (to you).
http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx

To me it seems like crossing a river to get water. Why not simply use select?
enumerable.Select(item =>
new SelectListItem{
Text = item.SomeProperty,
Value item.SomeOtherProperty
}).ToList();
if you really do want a method then you could do this:
public static
IEnumerable<SelectListItem> ToSelectItemList<TSource, TKey>(this
IEnumerable<TSource> enumerable, Func<TSource, TKey> text,
Func<TSource, TKey> value)
{
return (from item in enumerable
select new SelectListItem{
Text = text(item),
Value = value(item)
}).ToList();
}

A LINQ way of achieving what you want would be:
public static IEnumerable<SelectListItem> ToSelectItemList<TSource, TKey>(
this IEnumerable<TSource> enumerable,
Func<TSource, TKey> textSelector,
Func<TSource, TKey> valueSelector)
{
return from model in enumerable
select new SelectListItem
{
Text = textSelector(model),
Value = valueSelector(model)
};
}

Within the body of your extension method, those two parameters are just delegates, and you can run them like any other function:
selectList.Add(new SelectListItem() { Text = text(model), Value = value(model)});

Other solutions work as well, but I think that the one from Martin Liversage is the best way to do it:
IEnumerable<SelectListItem> selectListItems = items.Select(x =>
new SelectListItem
{
Text = x.TextProperty,
Value = x.ValueProperty
});

Related

Can I remove the need for the double lambda in this generic expression?

I've made this extension method (I know right now there's no exception checking etc, will be added once I'm sure the function is actually correct):
public static IEnumerable<TSource> ChangeProperty<TSource, TResult>(this IEnumerable<TSource> source,Expression<Func<TSource,TResult>> res, Func<TSource, TResult> changeProp)
{
Type type = typeof(TSource);
MemberExpression member = res.Body as MemberExpression;
var name = member.Member.Name;
foreach (var x in source)
{
var prop = type.GetProperty(name);
prop.SetValue(x, changeProp(x));
Console.WriteLine(prop.GetValue(x));
}
return source;
}
And is used in this context(Remove unwanted tags strips html tags out of a string):
_dc.EmailTemplates
.ChangeProperty(x=>x.Body,z=>RemoveUnwantedTags(z.Body))
.ToList();
But I don't like that I have to use a double lambda, one for getting the property name, and then one for executing the function. I don't know if it's my lack of understanding on how Expression<> works, or if im missing something really obvious but would really appreciate the help!
Similar to how ForEach is used in List<T> the desired functionality can be simplified to
public static IEnumerable<TSource> Apply<TSource>(this IEnumerable<TSource> source, Action<TSource> action) {
foreach (var item in source) {
action(item);
yield return item;
}
}
and used
_dc.EmailTemplates
.Apply(x => x.Body = RemoveUnwantedTags(x.Body))
.ToList();
This can also be used for multiple members by doing
_dc.EmailTemplates
.Apply(x => {
x.Body = RemoveUnwantedTags(x.Body);
x.SomeOtherMember = SomeOtherFunction(x.SomeOtherMember);
})
.ToList();

Extension of IEnumerable's Select to include the source in the selector

One of IEnumerable's overload is:
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult> selector);
In the selector I wish to include the source. I know this sounds counter-intuitive because you provide the source to Select in the first place, but JavaScript has something similar. I would want to use it in a quick situation like this one here:
var greetings = new List<string> { "John", "Keith", "Sarah", "Matt" }.Select((name, index, source) => {
if (name == source.First())
return $"{name} (Todays Winner)";
return name;
});
The above will have an error because Select's selector parameter does not return 3 values. Just the current object, and index. I want it to include the source.
I don't want to first create the list separately and then do .first on it.
Here is how far I've gone with the extension; I'm not sure how to implement it.
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult, IEnumerable<TSource>> selector)
{
//not sure what to put in here, must be missing something simple ;(
}
Update
The above situation is just a made up example. My actual case requires using .Last() not .First() so index won't be useful since we don't know what the last index will be, as opposed to zero being first. Hence my need for the source to be passed back.
This should do it:
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TSource>, TResult> selector)
{
using (var enumerator = source.GetEnumerator()) {
for (var i = 0 ; enumerator.MoveNext() ; i++) {
yield return selector(enumerator.Current, i, source);
}
}
}
Note that you have written the wrong type for the selector parameter. It should be Func<TSource, int, IEnumerable<TSource>, TResult>, not Func<TSource, int, TResult, IEnumerable<TSource>>.
If you just want to check if an element is the first, why not just check index == 0?
var greetings = new List<string> { "John", "Keith", "Sarah", "Matt" }.Select((name, index, source) => {
if (index == 0)
return $"{name} (Todays Winner)";
return name;
});
This should work:
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TSource>, TResult> selector)
{
int index = 0;
foreach(var item in source)
{
yield return selector(item, index, source);
index++;
}
}

Finding the minimal difference after filtering item result in `Sequence contains no elements` [duplicate]

I'm producing a list of decimal values from a LINQ expression and I want the minimum non zero value. However it's entirely possible that the LINQ expression will result in an empty list.
This will raise an exception and there is no MinOrDefault to cope with this situation.
decimal result = (from Item itm in itemList
where itm.Amount > 0
select itm.Amount).Min();
How can I set the result to 0 if the list is empty?
What you want is this:
IEnumerable<double> results = ... your query ...
double result = results.MinOrDefault();
Well, MinOrDefault() does not exist. But if we were to implement it ourselves it would look something like this:
public static class EnumerableExtensions
{
public static T MinOrDefault<T>(this IEnumerable<T> sequence)
{
if (sequence.Any())
{
return sequence.Min();
}
else
{
return default(T);
}
}
}
However, there is functionality in System.Linq that will produce the same result (in a slightly different way):
double result = results.DefaultIfEmpty().Min();
If the results sequence contains no elements, DefaultIfEmpty() will produce a sequence containing one element - the default(T) - which you subsequently can call Min() on.
If the default(T) is not what you want, then you could specify your own default with:
double myDefault = ...
double result = results.DefaultIfEmpty(myDefault).Min();
Now, that's neat!
decimal? result = (from Item itm in itemList
where itm.Amount != 0
select (decimal?)itm.Amount).Min();
Note the conversion to decimal?. You'll get an empty result if there are none (just handle that after the fact - I'm mainly illustrating how to stop the exception). I also made "non-zero" use != rather than >.
The neatest in terms of just doing it once in a small amount code is, as already mentioned:
decimal result = (from Item itm in itemList
where itm.Amount > 0
select itm.Amount).DefaultIfEmpty().Min();
With casting itm.Amount to decimal? and obtaining the Min of that being the neatest if we want to be able to detect this empty condition.
If however you want to actually provide a MinOrDefault() then we can of course start with:
public static TSource MinOrDefault<TSource>(this IQueryable<TSource> source, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).Min();
}
public static TSource MinOrDefault<TSource>(this IQueryable<TSource> source)
{
return source.DefaultIfEmpty(defaultValue).Min();
}
public static TResult MinOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).Min(selector);
}
public static TResult MinOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector)
{
return source.DefaultIfEmpty().Min(selector);
}
You now have a full set of MinOrDefault whether or not you include a selector, and whether or not you specify the default.
From this point on your code is simply:
decimal result = (from Item itm in itemList
where itm.Amount > 0
select itm.Amount).MinOrDefault();
So, while it's not as neat to begin with, it's neater from then on.
But wait! There's more!
Let's say you use EF and want to make use of the async support. Easily done:
public static Task<TSource> MinOrDefaultAsync<TSource>(this IQueryable<TSource> source, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).MinAsync();
}
public static Task<TSource> MinOrDefaultAsync<TSource>(this IQueryable<TSource> source)
{
return source.DefaultIfEmpty(defaultValue).MinAsync();
}
public static Task<TSource> MinOrDefaultAsync<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).MinAsync(selector);
}
public static Task<TSource> MinOrDefaultAsync<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector)
{
return source.DefaultIfEmpty().MinAsync(selector);
}
(Note that I don't use await here; we can directly create a Task<TSource> that does what we need without it, and hence avoid the hidden complications await brings).
But wait, there's more! Let's say we're using this with IEnumerable<T> some times. Our approach is sub-optimal. Surely we can do better!
First, the Min defined on int?, long?, float? double? and decimal? already do what we want anyway (as Marc Gravell's answer makes use of). Similarly, we also get the behaviour we want from the Min already defined if called for any other T?. So let's do some small, and hence easily inlined, methods to take advantage of this fact:
public static TSource? MinOrDefault<TSource>(this IEnumerable<TSource?> source, TSource? defaultValue) where TSource : struct
{
return source.Min() ?? defaultValue;
}
public static TSource? MinOrDefault<TSource>(this IEnumerable<TSource?> source) where TSource : struct
{
return source.Min();
}
public static TResult? Min<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult?> selector, TResult? defaultValue) where TResult : struct
{
return source.Min(selector) ?? defaultValue;
}
public static TResult? Min<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult?> selector) where TResult : struct
{
return source.Min(selector);
}
Now let's start with the more general case first:
public static TSource MinOrDefault<TSource>(this IEnumerable<TSource> source, TSource defaultValue)
{
if(default(TSource) == null) //Nullable type. Min already copes with empty sequences
{
//Note that the jitter generally removes this code completely when `TSource` is not nullable.
var result = source.Min();
return result == null ? defaultValue : result;
}
else
{
//Note that the jitter generally removes this code completely when `TSource` is nullable.
var comparer = Comparer<TSource>.Default;
using(var en = source.GetEnumerator())
if(en.MoveNext())
{
var currentMin = en.Current;
while(en.MoveNext())
{
var current = en.Current;
if(comparer.Compare(current, currentMin) < 0)
currentMin = current;
}
return currentMin;
}
}
return defaultValue;
}
Now the obvious overrides that make use of this:
public static TSource MinOrDefault<TSource>(this IEnumerable<TSource> source)
{
var defaultValue = default(TSource);
return defaultValue == null ? source.Min() : source.MinOrDefault(defaultValue);
}
public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector, TResult defaultValue)
{
return source.Select(selector).MinOrDefault(defaultValue);
}
public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
{
return source.Select(selector).MinOrDefault();
}
If we're really bullish about performance, we can optimise for certain cases, just like Enumerable.Min() does:
public static int MinOrDefault(this IEnumerable<int> source, int defaultValue)
{
using(var en = source.GetEnumerator())
if(en.MoveNext())
{
var currentMin = en.Current;
while(en.MoveNext())
{
var current = en.Current;
if(current < currentMin)
currentMin = current;
}
return currentMin;
}
return defaultValue;
}
public static int MinOrDefault(this IEnumerable<int> source)
{
return source.MinOrDefault(0);
}
public static int MinOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector, int defaultValue)
{
return source.Select(selector).MinOrDefault(defaultValue);
}
public static int MinOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector)
{
return source.Select(selector).MinOrDefault();
}
And so on for long, float, double and decimal to match the set of Min() provided by Enumerable. This is the sort of thing where T4 templates are useful.
At the end of all that, we have just about as performant an implementation of MinOrDefault() as we could hope for, for a wide range of types. Certainly not "neat" in the face of one use for it (again, just use DefaultIfEmpty().Min()), but very much "neat" if we find ourselves using it a lot, so we have a nice library we can reuse (or indeed, paste into answers on StackOverflow…).
This approach will return the single smallest Amount value from itemList. In theory this should avoid multiple round trips to the database.
decimal? result = (from Item itm in itemList
where itm.Amount > 0)
.Min(itm => (decimal?)itm.Amount);
The null reference exception is no longer caused because we are using a nullable type.
By avoiding the use of executing methods such as Any before calling Min, we should only be making one trip to the database
If itemList is non-nullable (where DefaultIfEmpty gives 0) and you want null as a potential output value, you can use the lambda syntax as well:
decimal? result = itemList.Where(x => x.Amount != 0).Min(x => (decimal?)x);
decimal result;
try{
result = (from Item itm in itemList
where itm.Amount != 0
select (decimal?)itm.Amount).Min();
}catch(Exception e){
result = 0;
}

DistinctBy not recognized as method

Maybe I am missing an using? (I have using System.Linq).
With Distinct no problem.
This is my command that i want to add DistinctBy:
List<Capture> list = db.MyObject.Where(x => x.prop == "Name").ToList();
You can add a extension method
public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> property)
{
return items.GroupBy(property).Select(x => x.First());
}
and You can use it like
List<Capture> list = db.MyObject.Where(x => x.prop == "Name")
.DistinctBy(y=> y.prop )
.ToList();
OR, You can use DistincyBy provided through MoreLinq.
Another example:
public static class ExtensionMethods
{
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
var seenKeys = new HashSet<TKey>();
foreach (TSource element in source)
{
if (seenKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
}
MyList.GroupBy(a=>a.item).select(a=>a.FirstOrDefault()).ToList();//use this
//is equal to
MyList.DistinctBy(a=>a.item).ToList();//its not work with linq
Now in dotnet 6.0 there is a built in DistinctBy extension in System.Linq namespace
https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.distinctby?view=net-6.0&viewFallbackFrom=net-5.0

How to achieve "MinOrDefault" in LINQ?

I'm producing a list of decimal values from a LINQ expression and I want the minimum non zero value. However it's entirely possible that the LINQ expression will result in an empty list.
This will raise an exception and there is no MinOrDefault to cope with this situation.
decimal result = (from Item itm in itemList
where itm.Amount > 0
select itm.Amount).Min();
How can I set the result to 0 if the list is empty?
What you want is this:
IEnumerable<double> results = ... your query ...
double result = results.MinOrDefault();
Well, MinOrDefault() does not exist. But if we were to implement it ourselves it would look something like this:
public static class EnumerableExtensions
{
public static T MinOrDefault<T>(this IEnumerable<T> sequence)
{
if (sequence.Any())
{
return sequence.Min();
}
else
{
return default(T);
}
}
}
However, there is functionality in System.Linq that will produce the same result (in a slightly different way):
double result = results.DefaultIfEmpty().Min();
If the results sequence contains no elements, DefaultIfEmpty() will produce a sequence containing one element - the default(T) - which you subsequently can call Min() on.
If the default(T) is not what you want, then you could specify your own default with:
double myDefault = ...
double result = results.DefaultIfEmpty(myDefault).Min();
Now, that's neat!
decimal? result = (from Item itm in itemList
where itm.Amount != 0
select (decimal?)itm.Amount).Min();
Note the conversion to decimal?. You'll get an empty result if there are none (just handle that after the fact - I'm mainly illustrating how to stop the exception). I also made "non-zero" use != rather than >.
The neatest in terms of just doing it once in a small amount code is, as already mentioned:
decimal result = (from Item itm in itemList
where itm.Amount > 0
select itm.Amount).DefaultIfEmpty().Min();
With casting itm.Amount to decimal? and obtaining the Min of that being the neatest if we want to be able to detect this empty condition.
If however you want to actually provide a MinOrDefault() then we can of course start with:
public static TSource MinOrDefault<TSource>(this IQueryable<TSource> source, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).Min();
}
public static TSource MinOrDefault<TSource>(this IQueryable<TSource> source)
{
return source.DefaultIfEmpty(defaultValue).Min();
}
public static TResult MinOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).Min(selector);
}
public static TResult MinOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector)
{
return source.DefaultIfEmpty().Min(selector);
}
You now have a full set of MinOrDefault whether or not you include a selector, and whether or not you specify the default.
From this point on your code is simply:
decimal result = (from Item itm in itemList
where itm.Amount > 0
select itm.Amount).MinOrDefault();
So, while it's not as neat to begin with, it's neater from then on.
But wait! There's more!
Let's say you use EF and want to make use of the async support. Easily done:
public static Task<TSource> MinOrDefaultAsync<TSource>(this IQueryable<TSource> source, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).MinAsync();
}
public static Task<TSource> MinOrDefaultAsync<TSource>(this IQueryable<TSource> source)
{
return source.DefaultIfEmpty(defaultValue).MinAsync();
}
public static Task<TSource> MinOrDefaultAsync<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, TSource defaultValue)
{
return source.DefaultIfEmpty(defaultValue).MinAsync(selector);
}
public static Task<TSource> MinOrDefaultAsync<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector)
{
return source.DefaultIfEmpty().MinAsync(selector);
}
(Note that I don't use await here; we can directly create a Task<TSource> that does what we need without it, and hence avoid the hidden complications await brings).
But wait, there's more! Let's say we're using this with IEnumerable<T> some times. Our approach is sub-optimal. Surely we can do better!
First, the Min defined on int?, long?, float? double? and decimal? already do what we want anyway (as Marc Gravell's answer makes use of). Similarly, we also get the behaviour we want from the Min already defined if called for any other T?. So let's do some small, and hence easily inlined, methods to take advantage of this fact:
public static TSource? MinOrDefault<TSource>(this IEnumerable<TSource?> source, TSource? defaultValue) where TSource : struct
{
return source.Min() ?? defaultValue;
}
public static TSource? MinOrDefault<TSource>(this IEnumerable<TSource?> source) where TSource : struct
{
return source.Min();
}
public static TResult? Min<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult?> selector, TResult? defaultValue) where TResult : struct
{
return source.Min(selector) ?? defaultValue;
}
public static TResult? Min<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult?> selector) where TResult : struct
{
return source.Min(selector);
}
Now let's start with the more general case first:
public static TSource MinOrDefault<TSource>(this IEnumerable<TSource> source, TSource defaultValue)
{
if(default(TSource) == null) //Nullable type. Min already copes with empty sequences
{
//Note that the jitter generally removes this code completely when `TSource` is not nullable.
var result = source.Min();
return result == null ? defaultValue : result;
}
else
{
//Note that the jitter generally removes this code completely when `TSource` is nullable.
var comparer = Comparer<TSource>.Default;
using(var en = source.GetEnumerator())
if(en.MoveNext())
{
var currentMin = en.Current;
while(en.MoveNext())
{
var current = en.Current;
if(comparer.Compare(current, currentMin) < 0)
currentMin = current;
}
return currentMin;
}
}
return defaultValue;
}
Now the obvious overrides that make use of this:
public static TSource MinOrDefault<TSource>(this IEnumerable<TSource> source)
{
var defaultValue = default(TSource);
return defaultValue == null ? source.Min() : source.MinOrDefault(defaultValue);
}
public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector, TResult defaultValue)
{
return source.Select(selector).MinOrDefault(defaultValue);
}
public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
{
return source.Select(selector).MinOrDefault();
}
If we're really bullish about performance, we can optimise for certain cases, just like Enumerable.Min() does:
public static int MinOrDefault(this IEnumerable<int> source, int defaultValue)
{
using(var en = source.GetEnumerator())
if(en.MoveNext())
{
var currentMin = en.Current;
while(en.MoveNext())
{
var current = en.Current;
if(current < currentMin)
currentMin = current;
}
return currentMin;
}
return defaultValue;
}
public static int MinOrDefault(this IEnumerable<int> source)
{
return source.MinOrDefault(0);
}
public static int MinOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector, int defaultValue)
{
return source.Select(selector).MinOrDefault(defaultValue);
}
public static int MinOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector)
{
return source.Select(selector).MinOrDefault();
}
And so on for long, float, double and decimal to match the set of Min() provided by Enumerable. This is the sort of thing where T4 templates are useful.
At the end of all that, we have just about as performant an implementation of MinOrDefault() as we could hope for, for a wide range of types. Certainly not "neat" in the face of one use for it (again, just use DefaultIfEmpty().Min()), but very much "neat" if we find ourselves using it a lot, so we have a nice library we can reuse (or indeed, paste into answers on StackOverflow…).
This approach will return the single smallest Amount value from itemList. In theory this should avoid multiple round trips to the database.
decimal? result = (from Item itm in itemList
where itm.Amount > 0)
.Min(itm => (decimal?)itm.Amount);
The null reference exception is no longer caused because we are using a nullable type.
By avoiding the use of executing methods such as Any before calling Min, we should only be making one trip to the database
If itemList is non-nullable (where DefaultIfEmpty gives 0) and you want null as a potential output value, you can use the lambda syntax as well:
decimal? result = itemList.Where(x => x.Amount != 0).Min(x => (decimal?)x);
decimal result;
try{
result = (from Item itm in itemList
where itm.Amount != 0
select (decimal?)itm.Amount).Min();
}catch(Exception e){
result = 0;
}

Categories