Hi David,
sorry for late reply. I fully agree with your point and also believe
that immutable data structures are niche fit for NGenerics. Your code
and codestyle from what I see agree with rules of of NGeenerics,
especially I like that they all come with unit tests. So they can go
to repository as they are.
I had a chat with fellow members and we would like to invite you to
become contributing member of NGenerics project along with us. If you
accept this, I will arrange a svn access for you and you can then go
forward and add the code above to Immmutable namespace.
Looking forward for your reply.
All the best.
Huseyn
On Oct 10, 12:33 pm, David Schmitt <
da...@dasz.at> wrote:
> husayt wrote:
> > Yes, indeed, I was very interested in thread-safe standard data
> > structures (stacks, lists,queues). But now there is a Task Parallel
> > Library (TPL -
http://en.wikipedia.org/wiki/Task_Parallel_Library#TPL),
> [PairTest.cs4K ]/*
> Copyright 2009 David Schmitt <
da...@dasz.at> (
http://dasz.at/)
>
> This program is licensed under the GNU Lesser General Public License (LGPL). You should
> have received a copy of the license along with the source code. If not, an online copy
> of the license can be found athttp://
www.gnu.org/copyleft/lesser.html.
> */
>
> using System;
> using NGenerics.DataStructures.General;
> using NUnit.Framework;
>
> namespace NGenerics.Tests.DataStructures.General
> {
> [TestFixture]
> public class PairTest
> {
> [TestFixture]
> public class Construction
> {
> private static void construct_and_test<T>(T a, T b)
> {
> var pair = new Pair<object>(a, b);
> Assert.AreEqual(pair.A, a);
> Assert.AreEqual(pair.B, b);
> }
>
> [Test]
> public void with_values()
> {
> construct_and_test(6, 11);
> }
>
> [Test]
> public void with_references()
> {
> construct_and_test(new object(), new object());
> }
>
> [Test]
> public void with_nulls()
> {
> construct_and_test(null, new object());
> construct_and_test(new object(), null);
> construct_and_test<object>(null, null);
> }
> }
>
> [TestFixture]
> public class Equality
> {
> private static void compare<T>(T a, T b)
> {
> var pairab1 = new Pair<T>(a, b);
> var pairab2 = new Pair<T>(a, b);
> var pairba = new Pair<T>(b, a);
>
> // copy of the reference to avoid warnings
> var pairab1ref = pairab1;
>
> Assert.AreEqual(pairab1, pairab1);
> Assert.AreEqual(pairab1, pairab2);
> Assert.AreEqual(pairab2, pairab1);
> Assert.AreNotEqual(pairab1, pairba);
>
> Assert.IsTrue(pairab1 == pairab1ref);
> Assert.IsTrue(pairab1 == pairab2);
> Assert.IsTrue(pairab2 == pairab1);
> Assert.IsFalse(pairab1 == pairba);
>
> Assert.IsFalse(pairab1 != pairab1ref);
> Assert.IsFalse(pairab1 != pairab2);
> Assert.IsFalse(pairab2 != pairab1);
> Assert.IsTrue(pairab1 != pairba);
>
> Assert.AreEqual(pairab1.GetHashCode(), pairab1.GetHashCode());
> Assert.AreEqual(pairab1.GetHashCode(), pairab2.GetHashCode());
> }
>
> [Test]
> public void with_values()
> {
> compare(6, 11);
> }
>
> [Test]
> public void with_references()
> {
> compare(new object(), new object());
> }
>
> [Test]
> public void with_nulls()
> {
> compare(null, new object());
> compare(new object(), null);
> }
> }
>
> [TestFixture]
> public class Transformations
> {
> private static void reverse<T>(T a, T b)
> {
> var pair = new Pair<T>(a, b);
>
> Assert.AreEqual(pair.Reverse().A, b);
> Assert.AreEqual(pair.Reverse().B, a);
> }
>
> [Test]
> public void TestReverse()
> {
> reverse(6, 11);
> reverse(new object(), new object());
> reverse(null, new object());
> reverse(new object(), null);
> reverse<object>(null, null);
> }
>
> [Test]
> [ExpectedException(typeof(ArgumentNullException))]
> public void TestReverseNull()
> {
> PairExtensions.Reverse<object>(null);
> }
>
> private static void keyvaluepair<T>(T a, T b)
> {
> var pair = new Pair<T>(a, b);
> var kvpair = new System.Collections.Generic.KeyValuePair<T, T>(a, b);
>
> Assert.AreEqual(pair.ToKeyValuePair(), kvpair);
> }
>
> [Test]
> public void TestToKeyValuePair()
> {
> keyvaluepair(6, 11);
> keyvaluepair(new object(), new object());
> keyvaluepair(null, new object());
> keyvaluepair(new object(), null);
> keyvaluepair<object>(null, null);
> }
>
> [Test]
> [ExpectedException(typeof(ArgumentNullException))]
> public void TestToKeyValuePairNull()
> {
> PairExtensions.ToKeyValuePair<object>(null);
> }
> }
> }
>
>
>
> }
>
>
>
> [Pair.cs7K ]/*
> Copyright 2009 David Schmitt <
da...@dasz.at> (
http://dasz.at/)
>
> This program is licensed under the GNU Lesser General Public License (LGPL). You should
> have received a copy of the license along with the source code. If not, an online copy
> of the license can be found athttp://
www.gnu.org/copyleft/lesser.html.
> */
>
> using System;
> using NGenerics.Util;
>
> namespace NGenerics.DataStructures.General
> {
> /// <summary>
> /// An immutable class representing a pair of values with value semantics.
> /// </summary>
> /// <typeparam name="T">The type of object the pair contains.</typeparam>
> #if (!SILVERLIGHT)
> [Serializable]
> #endif
> public class Pair<T>
> {
> #region Globals
>
> private readonly T a;
> private readonly T b;
>
> #endregion
>
> #region Construction
>
> /// <param name="a">The first value.</param>
> /// <param name="b">The other value.</param>
> public Pair(T a, T b)
> {
> this.a = a;
> this.b = b;
> }
>
> #endregion
>
> #region Public Members
>
> /// <summary>
> /// Gets the A-half of this <see cref="Pair{T}"/>.
> /// </summary>
> /// <value>The A-half.</value>
> public T A
> {
> get
> {
> return this.a;
> }
> }
>
> /// <summary>
> /// Gets the B-half of this <see cref="Pair{T}"/>.
> /// </summary>
> /// <value>The B-half.</value>
> public T B
> {
> get
> {
> return this.b;
> }
> }
>
> #endregion
>
> #region Object Overrides
>
> /// <summary>
> /// Creates a user-readable string representation of this Pair.
> /// </summary>
> /// <returns>A user-readable string.</returns>
> public override string ToString()
> {
> return String.Format("({0}, {1})", this.a, this.b);
> }
>
> /// <summary>
> /// Compares this Pair to another Pair, based on their parts.
> /// </summary>
> /// <param name="obj">The object to compare to.</param>
> /// <returns>If the <paramref name="obj"/> is a pair of the same objects as this pair, returns true. Returns false otherwise.</returns>
> public override bool Equals(object obj)
> {
> // shortcut reference equality
> if (Object.ReferenceEquals(this, obj))
> {
> return true;
> }
>
> var other = obj as Pair<T>;
>
> if (other == null)
> {
> return false;
> }
>
> return Object.Equals(this.a, other.a) && Object.Equals(this.b, other.b);
> }
>
> /// <summary>
> /// Calculates a hash code from this pair's constituents.
> /// </summary>
> /// <returns>A hashcode suitable for use in Hastables and similar structures.</returns>
> public override int GetHashCode()
> {
> return (Object.ReferenceEquals(this.a, null) ? 0 : this.a.GetHashCode())
> ^ (Object.ReferenceEquals(this.b, null) ? 0 : this.b.GetHashCode());
> }
>
> /// <summary>
> /// Compares the two Pairs based on their constituents.
> /// </summary>
> /// <param name="left">The first element to compare.</param>
> /// <param name="right">The second element to compare.</param>
> /// <returns>true, if both pairs have the same contents; false,otherwise.</returns>
> public static bool operator ==(Pair<T> left, Pair<T> right)
> {
> // shortcut reference equality
> if (Object.ReferenceEquals(left, right))
> {
> return true;
> }
>
> return Object.ReferenceEquals(left, null) || left.Equals(right);
> }
>
> /// <summary>
> /// Compares the two Pairs based on their constituents.
> /// </summary>
> /// <param name="left">The first element to compare.</param>
> /// <param name="right">The second element to compare.</param>
> /// <returns>false, if both pairs have the same contents; true,otherwise.</returns>
> public static bool operator !=(Pair<T> left, Pair<T> right)
> {
> return !(left == right);
> }
>
> #endregion
> }
>
> /// <summary>
> /// A few utility methods that do not need access to the private state of a <see cref="Pair{T}"/>.
> /// </summary>
> public static class PairExtensions
> {
> /// <summary>
> /// Creates a new <see cref="Pair{T}"/> with A and B switched.
> /// </summary>
> /// <typeparam name="T">The type contained in the <see cref="Pair{T}"/>.</typeparam>
> /// <param name="self">The pair whose constituents are used. May not be null.</param>
> /// <returns></returns>
> public static Pair<T> Reverse<T>(this Pair<T> self)
> {
> Guard.ArgumentNotNull(self, "self");
>
> if (Object.Equals(self.A, self.B))
> {
> return self;
> }
> else
> {
> return new Pair<T>(self.B, self.A);
> }
> }
>
> public static System.Collections.Generic.KeyValuePair<T, T> ToKeyValuePair<T>(this Pair<T> self)
> {
> return new System.Collections.Generic.KeyValuePair<T, T>(self.A, self.B);
> }
> }
>
>
>
> }