There isn't a built-in way of doing this, unfortunately - but it's really easy to write an extension method to do it.
It was in one of my very first blog posts, in fact... note that there's a better implementation in one of the comments. I'll move it into the body if I get time.
EDIT: Okay, I have a slightly abbreviated version - it just returns the maximal element, using the given selector. No need to do a projection as well - do that once afterwards if you need to. Note that you could remove the constraint on TValue
and use Comparer<TValue>.Default
instead, or have an overload which allows the comparison to be specified as another parameter.
public static TSource MaxBy<TSource, TValue>(this IEnumerable<TSource> source,
Func<TSource, TValue> selector)
where TValue : IComparable<TValue>
{
TValue maxValue = default(TValue);
TSource maxElement = default(TSource);
bool gotAny = false;
foreach (TSource sourceValue in source)
{
TValue value = selector(sourceValue);
if (!gotAny || value.CompareTo(maxValue) > 0)
{
maxValue = value;
maxElement = sourceValue;
gotAny = true;
}
}
if (!gotAny)
{
throw new InvalidOperationException("source is empty");
}
return maxElement;
}
Sample use: (note type inference):
string maxName = models.MaxBy(model => model.Name.Length).Name;