.NET 7 has a MinBy (and MaxBy) extension method but as we're limited to .NET Framework with AutoCAD, we need to build it (the following extension methods are taken from Gile.AutoCAD.Extension library).
public static class LinqExtension
{
/// <summary>
/// Gets the smallest item of the sequence using the default comparer with the 'selector' function returned values.
/// </summary>
/// <typeparam name="TSource">Type the items.</typeparam>
/// <typeparam name="TKey">Type of the returned value of 'selector' function.</typeparam>
/// <param name="source">Sequence to which the method applies.</param>
/// <param name="selector">Mapping function from 'TSource' to 'TKey'.</param>
/// <returns>The smallest item in the sequence.</returns>
/// <exception cref="System.ArgumentNullException">Thrown if 'source' is null.</exception>
/// <exception cref="System.ArgumentNullException">Thrown if 'selector' is null.</exception>
public static TSource MinBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> selector)
{
return source.MinBy(selector, Comparer<TKey>.Default);
}
/// <summary>
/// Gets the smallest item of the sequence using the 'comparer' with the 'selector' function returned values.
/// </summary>
/// <typeparam name="TSource">Type the items.</typeparam>
/// <typeparam name="TKey">Type of the returned value of 'selector' function.</typeparam>
/// <param name="source">Sequence to which the method applies.</param>
/// <param name="selector">Mapping function from 'TSource' to 'TKey'.</param>
/// <param name="comparer">Comparer used for the type 'TKey'.</param>
/// <returns>The smallest item in the sequence.</returns>
/// <exception cref="System.ArgumentNullException">Thrown if 'source' is null.</exception>
/// <exception cref="System.ArgumentNullException">Thrown if 'selector' is null.</exception>
/// <exception cref="System.ArgumentNullException">Thrown if 'comparer' is null.</exception>
public static TSource MinBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> selector,
IComparer<TKey> comparer)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (selector == null)
throw new ArgumentNullException(nameof(selector));
if (comparer == null)
throw new ArgumentNullException(nameof(comparer));
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
throw new InvalidOperationException("Empty sequence");
var min = iterator.Current;
var minKey = selector(min);
while (iterator.MoveNext())
{
var current = iterator.Current;
var currentKey = selector(current);
if (comparer.Compare(currentKey, minKey) < 0)
{
min = current;
minKey = currentKey;
}
}
return min;
}
}
}
Now the GetClosestCurve can be simply written:
public static Curve GetClosestCurve(IEnumerable<Curve> curves, Point3d pt) =>
curves.MinBy(c => pt.DistanceTo(c.GetClosestPointTo(pt, false)));