/// <summary> /// Because the input <see cref="IDictionary{TKey, TValue}"/> is not an <see cref="IDistinctValuedDictionary{TKey, TValue}"/>, duplicate value handling must be specified. /// </summary> public static Dictionary <TValue, TKey> Invert <TKey, TValue>(this IDictionary <TKey, TValue> dictionary, DuplicateValueHandling duplicateValueHandling = DuplicateValueHandling.Error) { var output = new Dictionary <TValue, TKey>(); foreach (var pair in dictionary) { var key = pair.Value; var value = pair.Key; if (output.ContainsKey(key)) { var existing = output[key]; var chosen = duplicateValueHandling.Choose(existing, value); output[key] = chosen; } else { output.Add(key, value); } } return(output); }
public static TValue Choose <TValue>(this DuplicateValueHandling duplicateValueHandling, TValue existing, TValue duplicate) { if (duplicateValueHandling.ChooseWouldFail(existing, duplicate, out TValue chosen)) { throw new DuplicateValueException <TValue>(existing, duplicate); } return(chosen); }
/// <summary> /// Note: assumes that <paramref name="existing"/> and <paramref name="duplicate"/> have already been determined to be duplicates. /// This method is meant for use in an if()-block, and informs as to whether choosing a duplicate would succeed, or if an exception would be thrown based on the <see cref="DuplicateValueHandling"/> value. /// In case of false, the output <paramref name="chosen"/> value is the default value of <typeparamref name="TValue"/>. /// In case of true, the chosen value is either the existing (<see cref="DuplicateValueHandling.KeepFirst"/>) or duplicate (<see cref="DuplicateValueHandling.UseLast"/>) value depending on the value of <paramref name="duplicateValueHandling"/>. /// </summary> public static bool ChooseWouldFail <TValue>(this DuplicateValueHandling duplicateValueHandling, TValue existing, TValue duplicate, out TValue chosen) { if (duplicateValueHandling == DuplicateValueHandling.Error) { chosen = default; return(true); } if (duplicateValueHandling == DuplicateValueHandling.KeepFirst) { chosen = existing; } else // Use last. { chosen = duplicate; } return(false); }