Skip to content
This repository has been archived by the owner on Dec 22, 2023. It is now read-only.

Commit

Permalink
Make ProjectionEqualityComparer helper public
Browse files Browse the repository at this point in the history
  • Loading branch information
louistakepillz committed May 5, 2015
1 parent c014e2d commit 8e429c1
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 108 deletions.
4 changes: 3 additions & 1 deletion ArgumentParser/ArgumentParser.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
<Compile Include="Arguments\PowerShell\PowerShellFlag.cs" />
<Compile Include="Arguments\PowerShell\PowerShellFlag`1.cs" />
<Compile Include="Arguments\ValueOptions.cs" />
<Compile Include="Helpers\ProjectionEqualityComparer.cs" />
<Compile Include="Helpers\ProjectionEqualityComparer`1.cs" />
<Compile Include="ParserBindingException.cs" />
<Compile Include="Reflection\IFlagOptionAttribute.cs" />
<Compile Include="Reflection\ICoupleableOptionAttribute.cs" />
Expand Down Expand Up @@ -94,7 +96,7 @@
<Compile Include="Reflection\POSIX\POSIXOptionAttribute.cs" />
<Compile Include="Key.cs" />
<Compile Include="ParameterPair.cs" />
<Compile Include="Helpers\ProjectionEqualityComparer.cs" />
<Compile Include="Helpers\ProjectionEqualityComparer`2.cs" />
<Compile Include="Helpers\StringArrayConverter.cs" />
<Compile Include="ParserExtension.cs" />
<Compile Include="ParsingException.cs" />
Expand Down
114 changes: 8 additions & 106 deletions ArgumentParser/Helpers/ProjectionEqualityComparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,124 +16,26 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/


using System;
using System.Collections.Generic;

namespace ArgumentParser.Helpers
{
// Taken from Jon Skeet's MiscUtil (http://jonskeet.uk/csharp/miscutil/)

/// <summary>
/// Non-generic class to produce instances of the generic class,
/// optionally using type inference.
/// Compares two objects for equivalence through a projected key.
/// </summary>
internal static class ProjectionEqualityComparer
public static class ProjectionEqualityComparer
{
/// <summary>
/// Creates an instance of ProjectionEqualityComparer using the specified projection.
/// Creates an instance of <see cref="T:ArgumentParser.Helpers.ProjectionEqualityComparer`2"/> using the specified projection.
/// </summary>
/// <typeparam name="TSource">Type parameter for the elements to be compared</typeparam>
/// <typeparam name="TKey">Type parameter for the keys to be compared, after being projected from the elements</typeparam>
/// <param name="projection">Projection to use when determining the key of an element</param>
/// <returns>A comparer which will compare elements by projecting each element to its key, and comparing keys</returns>
/// <typeparam name="TSource">The type of the elements to be compared.</typeparam>
/// <typeparam name="TKey">The type of the keys to be compared.</typeparam>
/// <param name="projection">The projection to use for extracting the compared key.</param>
/// <returns>A comparer that compares elements using a projected key.</returns>
public static ProjectionEqualityComparer<TSource, TKey> Create<TSource, TKey>(Func<TSource, TKey> projection)
{
return new ProjectionEqualityComparer<TSource, TKey>(projection);
}

/// <summary>
/// Creates an instance of ProjectionEqualityComparer using the specified projection.
/// The ignored parameter is solely present to aid type inference.
/// </summary>
/// <typeparam name="TSource">Type parameter for the elements to be compared</typeparam>
/// <typeparam name="TKey">Type parameter for the keys to be compared, after being projected from the elements</typeparam>
/// <param name="ignored">Value is ignored - type may be used by type inference</param>
/// <param name="projection">Projection to use when determining the key of an element</param>
/// <returns>A comparer which will compare elements by projecting each element to its key, and comparing keys</returns>
public static ProjectionEqualityComparer<TSource, TKey> Create<TSource, TKey>(TSource ignored, Func<TSource, TKey> projection)
{
return new ProjectionEqualityComparer<TSource, TKey>(projection);
}
}

/// <summary>
/// Class generic in the source only to produce instances of the
/// doubly generic class, optionally using type inference.
/// </summary>
internal static class ProjectionEqualityComparer<TSource>
{
/// <summary>
/// Creates an instance of ProjectionEqualityComparer using the specified projection.
/// </summary>
/// <typeparam name="TKey">Type parameter for the keys to be compared, after being projected from the elements</typeparam>
/// <param name="projection">Projection to use when determining the key of an element</param>
/// <returns>A comparer which will compare elements by projecting each element to its key, and comparing keys</returns>
public static ProjectionEqualityComparer<TSource, TKey> Create<TKey>(Func<TSource, TKey> projection)
{
return new ProjectionEqualityComparer<TSource, TKey>(projection);
}
}

/// <summary>
/// Comparer which projects each element of the comparison to a key, and then compares
/// those keys using the specified (or default) comparer for the key type.
/// </summary>
/// <typeparam name="TSource">Type of elements which this comparer will be asked to compare</typeparam>
/// <typeparam name="TKey">Type of the key projected from the element</typeparam>
internal class ProjectionEqualityComparer<TSource, TKey> : IEqualityComparer<TSource>
{
private readonly Func<TSource, TKey> projection;
private readonly IEqualityComparer<TKey> comparer;

/// <summary>
/// Creates a new instance using the specified projection, which must not be null.
/// The default comparer for the projected type is used.
/// </summary>
/// <param name="projection">Projection to use during comparisons</param>
public ProjectionEqualityComparer(Func<TSource, TKey> projection)
: this(projection, null) { }

/// <summary>
/// Creates a new instance using the specified projection, which must not be null.
/// </summary>
/// <param name="projection">Projection to use during comparisons</param>
/// <param name="comparer">The comparer to use on the keys. May be null, in
/// which case the default comparer will be used.</param>
public ProjectionEqualityComparer(Func<TSource, TKey> projection, IEqualityComparer<TKey> comparer)
{
if (projection == null)
throw new ArgumentNullException("projection");

this.comparer = comparer ?? EqualityComparer<TKey>.Default;
this.projection = projection;
}

/// <summary>
/// Compares the two specified values for equality by applying the projection
/// to each value and then using the equality comparer on the resulting keys. Null
/// references are never passed to the projection.
/// </summary>
public Boolean Equals(TSource x, TSource y)
{
if (x == null && y == null)
return true;
if (x == null || y == null)
return false;

return this.comparer.Equals(this.projection(x), this.projection(y));
}

/// <summary>
/// Produces a hash code for the given value by projecting it and
/// then asking the equality comparer to find the hash code of
/// the resulting key.
/// </summary>
public Int32 GetHashCode(TSource obj)
{
if (obj == null)
throw new ArgumentNullException("obj");

return this.comparer.GetHashCode(this.projection(obj));
}
}
}
41 changes: 41 additions & 0 deletions ArgumentParser/Helpers/ProjectionEqualityComparer`1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//-----------------------------------------------------------------------
// <copyright file="ProjectionEqualityComparer`1.cs" company="LouisTakePILLz">
// Copyright © 2015 LouisTakePILLz
// <author>LouisTakePILLz</author>
// </copyright>
//-----------------------------------------------------------------------

/*
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/


using System;

namespace ArgumentParser.Helpers
{
/// <summary>
/// Compares two objects for equivalence through a projected key.
/// </summary>
/// <typeparam name="TSource">The type of the elements to be compared.</typeparam>
public static class ProjectionEqualityComparer<TSource>
{
/// <summary>
/// Creates an instance of <see cref="T:ArgumentParser.Helpers.ProjectionEqualityComparer`2"/> using the specified projection.
/// </summary>
/// <typeparam name="TKey">The type of the keys to be compared.</typeparam>
/// <param name="projection">The projection to use for extracting the compared key.</param>
/// <returns>A comparer that compares elements using a projected key.</returns>
public static ProjectionEqualityComparer<TSource, TKey> Create<TKey>(Func<TSource, TKey> projection)
{
return new ProjectionEqualityComparer<TSource, TKey>(projection);
}
}
}
93 changes: 93 additions & 0 deletions ArgumentParser/Helpers/ProjectionEqualityComparer`2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//-----------------------------------------------------------------------
// <copyright file="ProjectionEqualityComparer`2.cs" company="LouisTakePILLz">
// Copyright © 2015 LouisTakePILLz
// <author>LouisTakePILLz</author>
// </copyright>
//-----------------------------------------------------------------------

/*
* This program is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections.Generic;

namespace ArgumentParser.Helpers
{
/// <summary>
/// Compares two objects for equivalence through a projected key.
/// </summary>
/// <typeparam name="TSource">The type of the source objects to compare.</typeparam>
/// <typeparam name="TKey">The type of the projected key.</typeparam>
public class ProjectionEqualityComparer<TSource, TKey> : IEqualityComparer<TSource>
{
private readonly Func<TSource, TKey> projection;
private readonly IEqualityComparer<TKey> comparer;

/// <summary>
/// Initializes a new instance of the <see cref="T:ArgumentParser.Helpers.ProjectionEqualityComparer"/> class using the default comparer.
/// </summary>
/// <param name="projection">The projection to use for extracting the compared key.</param>
public ProjectionEqualityComparer(Func<TSource, TKey> projection)
: this(projection, null) { }

/// <summary>
/// Initializes a new instance of the <see cref="T:ArgumentParser.Helpers.ProjectionEqualityComparer"/> class using the specified comparer.
/// </summary>
/// <param name="projection">The projection to use for extracting the compared key</param>
/// <param name="comparer">The comparer to use on the keys. May be null, in which case the default comparer will be used.</param>
public ProjectionEqualityComparer(Func<TSource, TKey> projection, IEqualityComparer<TKey> comparer)
{
if (projection == null)
throw new ArgumentNullException("projection");

this.comparer = comparer ?? EqualityComparer<TKey>.Default;
this.projection = projection;
}

/// <summary>
/// Creates an instance of <see cref="T:ArgumentParser.Helpers.ProjectionEqualityComparer`2"/> using the specified projection.
/// </summary>
/// <param name="projection">The projection to use for extracting the compared key</param>
/// <returns>A comparer that compares elements using a projected key.</returns>
public static ProjectionEqualityComparer<TSource, TKey> Create(Func<TSource, TKey> projection)
{
return new ProjectionEqualityComparer<TSource, TKey>(projection);
}

/// <summary>
/// Determines whether the specified objects are equal.
/// </summary>
/// <returns>A boolean value indicating whether the two objects are equal.</returns>
public Boolean Equals(TSource x, TSource y)
{
if (x == null && y == null)
return true;
if (x == null || y == null)
return false;

return this.comparer.Equals(this.projection(x), this.projection(y));
}

/// <summary>
/// Returns a hash code for the specified object.
/// </summary>
/// <returns>A hash code for the specified object.</returns>
/// <param name="obj">The <see cref="T:System.Object"/> for which a hash code is to be returned.</param>
/// <exception cref="T:System.ArgumentNullException">The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.</exception>
public int GetHashCode(TSource obj)
{
if (obj == null)
throw new ArgumentNullException("obj");

return this.comparer.GetHashCode(this.projection(obj));
}
}
}
2 changes: 1 addition & 1 deletion ArgumentParser/ParserOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using ArgumentParser.Reflection.POSIX;
using ArgumentParser.Reflection.PowerShell;
using ArgumentParser.Reflection.POSIX;
using ArgumentParser.Reflection.Windows;

namespace ArgumentParser
Expand Down

0 comments on commit 8e429c1

Please sign in to comment.