-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Closed as not planned
Labels
api-needs-workAPI needs work before it is approved, it is NOT ready for implementationAPI needs work before it is approved, it is NOT ready for implementationarea-System.Collections
Milestone
Description
There are many times when there is a custom equality comparison being done but I need access to the original instance.
What I'd like:
var mergedItems = new HashSet<Item>();
foreach (var item in items)
{
mergedItems.GetOrAdd(item).RelatedInfo.Add(x);
}
public sealed class Item : IEquatable<Item>
{
public DateTime Date { get; }
public int Amount { get; }
public List<int> RelatedInfo { get; }
public bool Equals(Item other) => other != null && other.Date == Date && other.Amount == Amount;
public override bool Equals(object obj) => obj is Item item && Equals(item);
public override int GetHashCode() => // ...
}Today I'm forced to use a Dictionary which duplicates storage of the key for no reason.
A dictionary is also wasteful because it has to do two hash lookups, one for TryGetValue and one for Add:
var mergedItems = new Dictionary<Item, Item>();
foreach (var item in items)
{
if (!mergedItems.TryGetValue(item, out var otherItem))
mergedItems.Add(item, otherItem = item);
otherItem.RelatedInfo.Add(x);
}This is no better; it's a lot more to maintain, unnecessarily coupled to the definition of equality, it's still duplicate storage of the key, and it's still duplicating the number of hash lookups:
var mergedItems = new Dictionary<(DateTime, int), Item>();
foreach (var item in items)
{
if (!mergedItems.TryGetValue((item.Date, item.Amount), out var otherItem))
mergedItems.Add((item.Date, item.Amount), otherItem = item);
otherItem.RelatedInfo.Add(x);
}KeyedCollection is the worst of all because in addition to the dictionary, it keeps a list I'll never use.
Proposed API
namespace System.Collections.Generic;
public class HashSet<T>
{
+ /// <summary>
+ /// Searches the set for a given element and returns the equal element it finds, if any;
+ /// otherwise, adds the element to the set.
+ /// </summary>
+ /// <param name="item">The element to search for, or to add to the set.</param>
+ /// <returns>
+ /// The equal element that the search found, or the given element that was added to the set.
+ /// </returns>
+ public T GetOrAdd(T item);
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
api-needs-workAPI needs work before it is approved, it is NOT ready for implementationAPI needs work before it is approved, it is NOT ready for implementationarea-System.Collections