dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.27k stars 4.73k forks source link

Allow creating a comparer from key selector #24376

Closed weitzhandler closed 4 years ago

weitzhandler commented 6 years ago

Suggestion

Please make another overload of the Comparer<T>.Create method that takes a Func<T, object> as a property selector, and will generate a comparer for the selected property.

Motive

Currently, if we want to create a comparer for a specific property in an item, we have this option (would love to hear about others):

var set = new SortedSet<User>(
 Comparer<User>.Create((u1, u2) => Comparer<string>.Default.Compare(u1.UserName, u2.UserName)));

My suggestion is that instead of having to create another comparer for the property, we should be able to create a comparer for any type by just specifying the property items should be compared by. So referring to the last example, it would look like this:

var set = new SortedList<User>(Comparer<User>.Create(u => u.UserName));

API Change

Expand the System.Collections.Generic.Comparer<T> class by adding the following overload of the Create method:

public static Comparer<T> Create(Func<T, object> propertySelector);

Which will build a Comparison<T> based on the provided lambda property.

jnm2 commented 6 years ago

Would use. I often end up declaring my own. I have an API like CustomComparer<T>.OrderBy(_ => _.Property1).ThenBy(_ => _.Property2). Think this is possible or useful in the BCL?

weitzhandler commented 6 years ago

Sounds good, but at least the basic functionality for conversion between the various types of comparisons and equalities should be part of the BCL.

safern commented 6 years ago

@weitzhandler thanks for your suggestion. After thinking this through with @ianhays we think this doesn't really saves much work, from the example that you included, the one using this proposed API, seems confusing to me on how the User is being compared, also, what if u.UserName is not a primitive nor IComparable type?

We don't think this API would add much value and save much work to people, basically it is going from a longer, clearer one liner, to a shorter and confusing one liner.

weitzhandler commented 6 years ago

@safern OK I respect your decision. Maybe there should be a tool that provides easy conversion between comparison and equality-comparison (any comparer is potentially an equality-comparer if their comparison value is zero).