Commit 260c6c5d authored by An Ionescu's avatar An Ionescu

Huge unforgivable commit. Full test coverage / fully working composite collections.

parent 4a896c51
......@@ -17,9 +17,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.Common", "src\Tests\Common\Tests.Common.csproj", "{BEAB10EF-BD0D-4144-9AD0-D3BD1C052246}"
ProjectSection(ProjectDependencies) = postProject
{AD1A36AB-C528-4507-9B45-F75F1806C7B1} = {AD1A36AB-C528-4507-9B45-F75F1806C7B1}
{CA98F1BE-E77B-4B55-9B87-4F4F6F7BF412} = {CA98F1BE-E77B-4B55-9B87-4F4F6F7BF412}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NUnitFixtureDependent", "src\NUnitFixtureDependent\NUnitFixtureDependent.csproj", "{AD1A36AB-C528-4507-9B45-F75F1806C7B1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -38,6 +41,10 @@ Global
{BEAB10EF-BD0D-4144-9AD0-D3BD1C052246}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BEAB10EF-BD0D-4144-9AD0-D3BD1C052246}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BEAB10EF-BD0D-4144-9AD0-D3BD1C052246}.Release|Any CPU.Build.0 = Release|Any CPU
{AD1A36AB-C528-4507-9B45-F75F1806C7B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AD1A36AB-C528-4507-9B45-F75F1806C7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AD1A36AB-C528-4507-9B45-F75F1806C7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AD1A36AB-C528-4507-9B45-F75F1806C7B1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
using System;
using System.Collections.Generic;
namespace Anvoker.Collections.Maps
{
public class CollectionEqualityComparer<T, TCollection>
: ICollectionEqualityComparer<T, TCollection>,
IEquatable<CollectionEqualityComparer<T, TCollection>>
where TCollection : IEnumerable<T>
{
private IEqualityComparer<T> comparerValue;
public CollectionEqualityComparer(IEqualityComparer<T> comparerValue)
{
this.comparerValue = comparerValue;
}
public CollectionEqualityComparer()
{
comparerValue = EqualityComparer<T>.Default;
}
public static CollectionEqualityComparer<T, TCollection> Default
=> new CollectionEqualityComparer<T, TCollection>();
public bool Equals(TCollection x, TCollection y)
{
var hashSetX = x as HashSet<T>
?? new HashSet<T>(x, comparerValue);
return hashSetX.SetEquals(y);
}
public bool Equals(CollectionEqualityComparer<T, TCollection> other)
=> other.comparerValue == comparerValue;
public int GetHashCode(TCollection obj)
{
int hash = 12582917;
foreach (T val in obj)
{
unchecked
{
hash *= 786433 + comparerValue.GetHashCode(val);
}
}
return hash;
}
}
}
\ No newline at end of file
......@@ -3,13 +3,48 @@
namespace Anvoker.Collections.Maps
{
/// <summary>
/// Represents a generic collection of key-value pairs where keys can be
/// Represents a generic collection of keys and values where keys can be
/// retrieved by their associated value.
/// </summary>
/// <typeparam name="TKey">The type of the keys.</typeparam>
/// <typeparam name="TVal">The type of the values.</typeparam>
public interface IBiMap<TKey, TVal> :
IDictionary<TKey, TVal>,
IFixedKeysBiMap<TKey, TVal>
{ }
/// <typeparam name="TKey">The type of the keys
/// <see cref="IBiMap{TKey, TVal}"/>.</typeparam>
/// <typeparam name="TVal">The type of the values
/// <see cref="IBiMap{TKey, TVal}"/>.</typeparam>
public interface IBiMap<TKey, TVal> : IFixedKeysBiMap<TKey, TVal>
{
/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <param name="key">The key of the value to get or set.</param>
/// <returns>The value associated with the specified key. If the
/// specified key is not found, a get operation throws a
/// <see cref="KeyNotFoundException"/>, and a set operation creates a
/// new element with the specified key.</returns>
new TVal this[TKey key] { get; set; }
/// <summary>
/// Adds the specified key and value to the
/// <see cref="IBiMap{TKey, TVal}"/>.
/// </summary>
/// <param name="key">The key of the element to add.</param>
/// <param name="value">The value of the element to add. The value can
/// be null for reference types.</param>
void Add(TKey key, TVal value);
/// <summary>
/// Removes all keys and values from the
/// <see cref="IBiMap{TKey, TVal}"/>.
/// </summary>
void Clear();
/// <summary>
/// Removes the element with the specified key from the
/// <see cref="IBiMap{TKey, TVal}"/>.
/// </summary>
/// <param name="key">The key of the element to remove.</param>
/// <returns>true if the element is successfully found and removed;
/// otherwise, false. This method returns false if key is not found in
/// the <see cref="IBiMap{TKey, TVal}"/>.</returns>
bool Remove(TKey key);
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
namespace Anvoker.Collections.Maps
{
public interface ICollectionEqualityComparer<T, TCollection>
: IEqualityComparer<TCollection>
where TCollection : IEnumerable<T>
{
}
}
\ No newline at end of file
using System.Collections.Generic;
namespace Anvoker.Collections.Maps
namespace Anvoker.Collections.Maps
{
/// <summary>
/// Represents a generic collection of key-value pairs where the values can
/// be changed but keys cannot be added or removed.
/// Represents a generic collection of keys and values where keys cannot be
/// added or removed and where keys can be retrieved by their associated
/// value.
/// </summary>
/// <typeparam name="TKey">The type of the keys.</typeparam>
/// <typeparam name="TVal">The type of the values.</typeparam>
/// <typeparam name="TKey">The type of the keys
/// <see cref="IFixedKeysBiMap{TKey, TVal}"/>.</typeparam>
/// <typeparam name="TVal">The type of the values
/// <see cref="IFixedKeysBiMap{TKey, TVal}"/>.</typeparam>
public interface IFixedKeysBiMap<TKey, TVal> :
IReadOnlyBiMap<TKey, TVal>
{
/// <summary>
/// Gets all keys that are associated with the specified value.
/// </summary>
/// <param name="val">The value to locate the keys by.</param>
/// <returns>A read-only collection with all of the associated keys.
/// </returns>
IReadOnlyCollection<TKey> this[TVal val] { get; }
/// <summary>
/// Replaces the value currently associated with the specified key.
/// Replaces the value currently associated with the specified key with
/// a new value.
/// </summary>
/// <param name="key">The key of the value to replace.</param>
/// <param name="value">The new value.</param>
......
......@@ -3,12 +3,14 @@
namespace Anvoker.Collections.Maps
{
/// <summary>
/// Represents a generic collection of key-values elements where keys
/// can be retrieved by their associated values and elements cannot be
/// added or removed.
/// Represents a generic collection of keys and values where keys cannot be
/// removed or added, where each key may be associated with multiple
/// values, and where keys can be retrieved by their associated values.
/// </summary>
/// <typeparam name="TKey">The type of the keys.</typeparam>
/// <typeparam name="TVal">The type of the values.</typeparam>
/// <typeparam name="TKey">The type of the keys
/// <see cref="IFixedKeysMultiBiMap{TKey, TVal}"/>.</typeparam>
/// <typeparam name="TVal">The type of the values
/// <see cref="IFixedKeysMultiBiMap{TKey, TVal}"/>.</typeparam>
public interface IFixedKeysMultiBiMap<TKey, TVal> :
IFixedKeysMultiMap<TKey, TVal>,
IFixedKeysBiMap<TKey, IReadOnlyCollection<TVal>>,
......
......@@ -3,11 +3,14 @@
namespace Anvoker.Collections.Maps
{
/// <summary>
/// Represents a generic collection of key-values elements where
/// elements cannot be added or removed.
/// Represents a generic collection of keys and values where keys cannot be
/// added or removed and where each key may be associated with multiple
/// values.
/// </summary>
/// <typeparam name="TKey">The type of the keys.</typeparam>
/// <typeparam name="TVal">The type of the values.</typeparam>
/// <typeparam name="TKey">The type of the keys
/// <see cref="IFixedKeysMultiMap{TKey, TVal}"/>.</typeparam>
/// <typeparam name="TVal">The type of the values
/// <see cref="IFixedKeysMultiMap{TKey, TVal}"/>.</typeparam>
public interface IFixedKeysMultiMap<TKey, TVal> :
IReadOnlyMultiMap<TKey, TVal>
{
......@@ -33,8 +36,6 @@ namespace Anvoker.Collections.Maps
/// added; otherwise, false.</returns>
bool AddValues(TKey key, IEnumerable<TVal> values);
void Replace(TKey key, IEnumerable<TVal> values);
/// <summary>
/// Removes the value associated with the specified key from the
/// <see cref="IFixedKeysMultiMap{TKey, TVal}"/>.
......@@ -66,5 +67,13 @@ namespace Anvoker.Collections.Maps
/// <returns>true if the element is successfully found and its values
/// removed; otherwise, false.</returns>
bool RemoveValuesAll(TKey key);
/// <summary>
/// Replaces the values currently associated with the specified key with
/// a new collection of values.
/// </summary>
/// <param name="key">The key of the value to replace.</param>
/// <param name="values">The new values.</param>
void Replace(TKey key, IEnumerable<TVal> values);
}
}
\ No newline at end of file
using System.Collections.Generic;
namespace Anvoker.Collections.Maps
namespace Anvoker.Collections.Maps
{
/// <summary>
/// Represents a generic collection of key-values elements where keys
/// can be retrieved by their associated values.
/// Represents a generic collection of keys and values where each key may be
/// associated with multiple values, and where keys can be retrieved by
/// their associated values.
/// </summary>
/// <typeparam name="TKey">The type of the keys.</typeparam>
/// <typeparam name="TVal">The type of the values.</typeparam>
/// <typeparam name="TKey">The type of the keys
/// <see cref="IMultiBiMap{TKey, TVal}"/>.</typeparam>
/// <typeparam name="TVal">The type of the values
/// <see cref="IMultiBiMap{TKey, TVal}"/>.</typeparam>
public interface IMultiBiMap<TKey, TVal> :
IFixedKeysMultiBiMap<TKey, TVal>,
IMultiMap<TKey, TVal>
......
......@@ -3,78 +3,54 @@
namespace Anvoker.Collections.Maps
{
/// <summary>
/// Represents a generic collection of key-values elements.
/// Represents a generic collection of keys and values where each key may be
/// associated with multiple values.
/// </summary>
/// <typeparam name="TKey">The type of the keys.</typeparam>
/// <typeparam name="TVal">The type of the values.</typeparam>
/// <typeparam name="TKey">The type of the keys
/// <see cref="IMultiMap{TKey, TVal}"/>.</typeparam>
/// <typeparam name="TVal">The type of the values
/// <see cref="IMultiMap{TKey, TVal}"/>.</typeparam>
public interface IMultiMap<TKey, TVal> :
IDictionary<TKey, ICollection<TVal>>,
IFixedKeysMultiMap<TKey, TVal>
{
/// <summary>
/// Gets the number of elements contained in the
/// <see cref="IMultiMap{TKey, TVal}"/>
/// </summary>
new int Count { get; }
new IReadOnlyCollection<TKey> Keys { get; }
new IReadOnlyCollection<IReadOnlyCollection<TVal>> Values { get; }
new IEnumerable<TVal> this[TKey key] { get; set; }
new IEnumerator<KeyValuePair<TKey, ICollection<TVal>>> GetEnumerator();
new bool TryGetValue(TKey key, out ICollection<TVal> values);
/// <summary>
/// Determines whether the <see cref="IMultiMap{TKey, TVal}"/> contains
/// a specific key.
/// </summary>
/// <param name="key">The key to locate in the
/// <see cref="IMultiMap{TKey, TVal}"/>.</param>
/// <returns>true if the <see cref="IMultiMap{TKey, TVal}"/> contains
/// an element with the specified key; otherwise, false.</returns>
new bool ContainsKey(TKey key);
/// <summary>
/// Adds the specified key to the
/// <see cref="IMultiMap{TKey, TVal}"/> with an empty value
/// collection.
/// Adds the specified key to the <see cref="IMultiMap{TKey, TVal}"/>
/// with no associated values.
/// </summary>
/// <param name="key">The key of the element to add.</param>
void AddKey(TKey key);
void Add(TKey key);
/// <summary>
/// Adds the specified key and its associated value to the
/// Adds the specified key and value to the
/// <see cref="IMultiMap{TKey, TVal}"/>.
/// </summary>
/// <param name="key">The key of the element to add.</param>
/// <param name="value">The value of the element to add. The value can
/// be null for reference types.</param>
void AddKey(TKey key, TVal value);
void Add(TKey key, TVal value);
/// <summary>
/// Adds the specified key and its associated values to the
/// Adds the specified key and values to the
/// <see cref="IMultiMap{TKey, TVal}"/>.
/// </summary>
/// <param name="key">The key of the element to add.</param>
/// <param name="values">The values of the element to add. The value can
/// be null for reference types.</param>
void AddKey(TKey key, IEnumerable<TVal> values);
/// <param name="values">The values of the element to add.</param>
void Add(TKey key, IEnumerable<TVal> values);
/// <summary>
/// Removes all keys and values from the
/// <see cref="IMultiMap{TKey, TVal}"/>.
/// </summary>
void Clear();
/// <summary>
/// Determines whether the <see cref="IMultiMap{TKey, TVal}"/> contains
/// all of the specified values at the specified key.
/// Removes the element with the specified key from the
/// <see cref="IMultiMap{TKey, TVal}"/>.
/// </summary>
/// <param name="key">The key to locate in the
/// <see cref="IMultiMap{TKey, TVal}"/>.</param>
/// <param name="values">The values to locate in the
/// <see cref="IMultiMap{TKey, TVal}"/>. The value can be null for
/// reference types.</param>
/// <returns>true if the <see cref="IMultiMap{TKey, TVal}"/> contains
/// an element with the specified key and values; otherwise, false.
/// </returns>
bool ContainsKeyWithValues(TKey key, IEnumerable<TVal> values);
/// <param name="key">The key of the element to remove.</param>
/// <returns>true if the element is successfully found and removed;
/// otherwise, false. This method returns false if key is not found in
/// the <see cref="IMultiMap{TKey, TVal}"/>.</returns>
bool Remove(TKey key);
}
}
\ No newline at end of file
......@@ -3,52 +3,44 @@
namespace Anvoker.Collections.Maps
{
/// <summary>
/// Represents a generic read-only collection of key-value pairs where keys
/// Represents a generic read-only collection of keys and values where keys
/// can be retrieved by their associated value.
/// </summary>
/// <typeparam name="TKey">The type of the keys.</typeparam>
/// <typeparam name="TVal">The type of the values.</typeparam>
/// <typeparam name="TKey">The type of the keys
/// <see cref="IReadOnlyBiMap{TKey, TVal}"/>.</typeparam>
/// <typeparam name="TVal">The type of the values
/// <see cref="IReadOnlyBiMap{TKey, TVal}"/>.</typeparam>
public interface IReadOnlyBiMap<TKey, TVal> :
IReadOnlyDictionary<TKey, TVal>
{
/// <summary>
/// Gets the <see cref="IEqualityComparer{T}"/> that is used to
/// determine equality of keys for the
/// <see cref="IReadOnlyBiMap{TKey, TVal}"/>.
/// determine equality of keys for the map.
/// </summary>
IEqualityComparer<TKey> ComparerKey { get; }
/// <summary>
/// Gets the <see cref="IEqualityComparer{T}"/> that is used to
/// determine equality of values for the
/// <see cref="IReadOnlyBiMap{TKey, TVal}"/>.
/// determine equality of values for the map.
/// </summary>
IEqualityComparer<TVal> ComparerValue { get; }
/// <summary>
/// Gets the number of unique values in the
/// <see cref="IReadOnlyBiMap{TKey, TVal}"/>.
/// </summary>
int UniqueValueCount { get; }
/// <summary>
/// Determines whether the <see cref="IReadOnlyBiMap{TKey, TVal}"/>
/// contains a specific value.
/// contains an element that has the specified value.
/// </summary>
/// <param name="value">The value to locate in the
/// <see cref="IReadOnlyBiMap{TKey, TVal}"/>. The value can be null for
/// reference types.</param>
/// <param name="value">The value to locate.</param>
/// <returns>true if the <see cref="IReadOnlyBiMap{TKey, TVal}"/>
/// contains an element with the specified value; otherwise,
/// contains an element that has the specified value; otherwise,
/// false.</returns>
bool ContainsValue(TVal value);
/// <summary>
/// Gets all keys that are associated with the specified value.
/// Gets all keys associated with the specified value.
/// </summary>
/// <param name="value">The value to locate the keys by.</param>
/// <returns>A read-only collection with all of the associated keys.
/// </returns>
IReadOnlyCollection<TKey> GetKeysWithValue(TVal value);
/// <param name="value">The value to locate.</param>
/// <returns>A read-only collection containing all keys associated
/// with the specified value.</returns>
IEnumerable<TKey> GetKeysWithValue(TVal value);
}
}
\ No newline at end of file
using System.Collections.Generic;
using System;
using System.Collections.Generic;
namespace Anvoker.Collections.Maps
{
/// <summary>
/// Represents a generic read-only collection of key-values elements where
/// keys can be retrieved by their associated values.
/// Represents a read-only generic collection of keys and values where each
/// key may be associated with multiple values, and where keys can be
/// retrieved by their associated values.
/// </summary>
/// <typeparam name="TKey">The type of the keys.</typeparam>
/// <typeparam name="TVal">The type of the values.</typeparam>
/// <typeparam name="TKey">The type of the keys
/// <see cref="IReadOnlyMultiBiMap{TKey, TVal}"/>.</typeparam>
/// <typeparam name="TVal">The type of the values
/// <see cref="IReadOnlyMultiBiMap{TKey, TVal}"/>.</typeparam>
public interface IReadOnlyMultiBiMap<TKey, TVal> :
IReadOnlyMultiMap<TKey, TVal>,
IReadOnlyBiMap<TKey, IReadOnlyCollection<TVal>>
{
/// <summary>
/// Gets the key associated with the specified value collection, using
/// reference equality on the collection.
/// Gets the <see cref="IEqualityComparer{T}"/> that is used to
/// determine equality of keys for the
/// <see cref="IReadOnlyMultiBiMap{TKey, TVal}"/>.
/// </summary>
/// <param name="values">The value collection of the key to get.</param>
/// <param name="key">When this method returns, contains the key
/// associated with the value collection, if the collection is found;
/// otherwise, the default value for the type of the key parameter.
/// This parameter is passed uninitialized.</param>
/// <returns>true if <see cref="IReadOnlyMultiBiMap{TKey, TVal}"/>
/// contains a key with the specified collection; otherwise false.
/// </returns>
bool TryGetKeyByCollectionRef(
IEnumerable<TVal> values, out TKey key);
new IEqualityComparer<TKey> ComparerKey { get; }
/// <summary>
/// Gets keys whose associated value collection satisfies set equality
/// with the specified collection.
/// Gets the <see cref="IEqualityComparer{T}"/> that is used to
/// determine equality of values for the
/// <see cref="IReadOnlyMultiBiMap{TKey, TVal}"/>.
/// </summary>
/// <param name="values">The collection of values to search by.</param>
/// <returns>An enumeration of all of the associated keys.
/// </returns>
IEnumerable<TKey> GetKeysWithEqualSet(
IEnumerable<TVal> values,
bool ignoreKeysWithNoValues = true);
new IEqualityComparer<TVal> ComparerValue { get; }
/// <summary>
/// Gets keys whose associated value collection is a superset of the
/// specified collection.
/// Gets all keys whose collection of associated values passes the
/// conditions specified in the <paramref name="selector"/>.
/// </summary>
/// <param name="values">The collection of values to search by.</param>
/// <returns>An enumeration of all of the associated keys.
/// </returns>
IEnumerable<TKey> GetKeysWithSuperset(
IEnumerable<TVal> values,
bool ignoreKeysWithNoValues = true);
/// <param name="selector">The predicate that selects which keys
/// to return based on their value collection.</param>
/// <returns>An enumeration of all selected keys.</returns>
IEnumerable<TKey> GetKeys(Func<IEnumerable<TVal>, bool> selector);
/// <summary>
/// Gets keys whose associated value collection is a subset of the
/// specified collection.
/// Gets all keys that have any values in common with the specified
/// collection.
/// </summary>
/// <param name="values">The collection of values to search by.</param>
/// <returns>An enumeration of all of the associated keys.
/// </returns>
IEnumerable<TKey> GetKeysWithSubset(
IEnumerable<TVal> values,
bool ignoreKeysWithNoValues = true);
/// <param name="values">The values to test against for overlap.</param>
/// <returns>An enumeration containing all keys whose value collection
/// has any values in common with the specified collection.</returns>
IEnumerable<TKey> GetKeysWithAny(IEnumerable<TVal> values);
/// <summary>
/// Gets keys whose associated value collection has at least one value
/// in common with the specified collection.
/// Gets all keys associated with the specified value.
/// </summary>
/// <param name="values">The collection of values to search by.</param>
/// <returns>An enumeration of all of the associated keys.
/// </returns>
IEnumerable<TKey> GetKeysWithAny(IEnumerable<TVal> values);
/// <param name="value">The value to locate.</param>
/// <returns>An enumeration containing all keys associated with the
/// specified value.</returns>
IEnumerable<TKey> GetKeysWithValue(TVal value);
}
}
\ No newline at end of file