diff --git a/Application/iSynaptic.Commons/Collections/Concurrent/ConcurrentDictionaryExtensions.cs b/Application/iSynaptic.Commons/Collections/Concurrent/ConcurrentDictionaryExtensions.cs new file mode 100644 index 0000000..59931d4 --- /dev/null +++ b/Application/iSynaptic.Commons/Collections/Concurrent/ConcurrentDictionaryExtensions.cs @@ -0,0 +1,41 @@ +// The MIT License +// +// Copyright (c) 2013 Jordan E. Terrell +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Collections.Concurrent; + +namespace iSynaptic.Commons.Collections.Concurrent +{ + public static class ConcurrentDictionaryExtensions + { + public static Maybe TryGetValue(this ConcurrentDictionary @this, TKey key) + { + Guard.NotNull(@this, "@this"); + + TValue retreivedValue = default(TValue); + + return @this + .ToMaybe() + .Where(x => x.TryGetValue(key, out retreivedValue)) + .Select(x => retreivedValue); + } + } +} diff --git a/Application/iSynaptic.Commons/Linq/EnumerableExtensions.cs b/Application/iSynaptic.Commons/Linq/EnumerableExtensions.cs index 3ada804..1fa2d2d 100644 --- a/Application/iSynaptic.Commons/Linq/EnumerableExtensions.cs +++ b/Application/iSynaptic.Commons/Linq/EnumerableExtensions.cs @@ -50,33 +50,34 @@ public static IEnumerable SelectMaybe(this IEnumerable @ .Select(x => x.Value); } - public static bool None(this IEnumerable @this) + public static bool None(this IEnumerable @this) { - return Guard.NotNull(@this, "@this") - .All(x => !x); + return !Guard.NotNull(@this, "this").Any(); } public static bool None(this IEnumerable @this, Func predicate) { - return Guard.NotNull(@this, "@this") - .All(x => !predicate(x)); + return !Guard.NotNull(@this, "this").Any(predicate); } - public static bool All(this IEnumerable @this) + public static bool AllTrue(this IEnumerable @this) { - return Guard.NotNull(@this, "@this") - .All(x => x); + return Guard.NotNull(@this, "this").All(x => x); + } + + public static bool AllFalse(this IEnumerable @this) + { + return Guard.NotNull(@this, "this").All(x => !x); } public static bool Any(this IEnumerable @this) { - return Guard.NotNull(@this, "@this") - .Any(x => x); + return Guard.NotNull(@this, "this").Any(x => x); } public static IEnumerable Let(this IEnumerable @this, Func, IEnumerable> selector) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(selector, "selector"); return LetCore(@this, selector); @@ -90,7 +91,7 @@ private static IEnumerable LetCore(IEnumerable @this, Fu public static IEnumerable Unless(this IEnumerable @this, Func predicate) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(predicate, "predicate"); return @this.Where(x => !predicate(x)); @@ -99,14 +100,14 @@ public static IEnumerable Unless(this IEnumerable @this, Func public static IEnumerable NotNull(this IEnumerable @this) where T : class { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); return @this.Where(x => x != null); } public static IEnumerable NotNull(this IEnumerable @this) where T : struct { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); return @this.Where(x => x.HasValue).Select(x => x.Value); } @@ -117,7 +118,7 @@ public static IOrderedEnumerable OrderBy(this IEnumerable OrderBy(this IEnumerable @this, Func keySelector, Func comparer) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(keySelector, "keySelector"); Guard.NotNull(comparer, "comparer"); @@ -131,7 +132,7 @@ public static IOrderedEnumerable OrderByDescending(this IEnume public static IOrderedEnumerable OrderByDescending(this IEnumerable @this, Func keySelector, Func comparer) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(keySelector, "keySelector"); Guard.NotNull(comparer, "comparer"); @@ -140,7 +141,7 @@ public static IOrderedEnumerable OrderByDescending(this public static IOrderedEnumerable OrderByPriorities(this IEnumerable @this, Func higherPrioritySelector, params Func[] additionalPrioritySelectors) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(higherPrioritySelector, "higherPrioritySelector"); return @this.OrderByPriorities((l, r) => higherPrioritySelector(l), additionalPrioritySelectors != null @@ -150,7 +151,7 @@ public static IOrderedEnumerable OrderByPriorities(this IEnume public static IOrderedEnumerable OrderByPriorities(this IEnumerable @this, Func higherPrioritySelector, params Func[] additionalPrioritySelectors) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(higherPrioritySelector, "higherPrioritySelector"); IEnumerable> selectors = new[] { higherPrioritySelector }; @@ -167,7 +168,7 @@ where leftHasPriority ^ rightHasPriority public static IEnumerable Distinct(this IEnumerable @this, Func selector) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(selector, "selector"); return @this.Distinct(selector.ToEqualityComparer()); @@ -175,7 +176,7 @@ public static IEnumerable Distinct(this IEnumerable @this, Func(this IEnumerable @this, T[] array, int index) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(array, "array"); var buffer = new List(); @@ -188,7 +189,7 @@ public static void CopyTo(this IEnumerable @this, T[] array, int index) public static IEnumerable> WithIndex(this IEnumerable @this) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); int index = 0; return @this.Select(x => new IndexedValue(index++, x)); @@ -196,19 +197,19 @@ public static IEnumerable> WithIndex(this IEnumerable @thi public static IEnumerable> AsLookAheadable(this IEnumerable @this) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); return new LookAheadEnumerable(@this); } public static IEnumerable Buffer(this IEnumerable @this) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); return @this.ToArray(); } public static IEnumerable> Batch(this IEnumerable @this, int batchSize) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); if (batchSize < 0) throw new ArgumentOutOfRangeException("batchSize", "Batch size must not be negative."); @@ -243,20 +244,20 @@ private static IEnumerable> BatchCore(IEnumerable @this, int batc public static Dictionary ToDictionary(this IEnumerable> @this) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); return @this.ToDictionary(x => x.Key, x => x.Value); } public static ReadOnlyDictionary ToReadOnlyDictionary(this IEnumerable> @this) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); return DictionaryExtensions.ToReadOnlyDictionary(@this.ToDictionary()); } public static string Delimit(this IEnumerable @this, string delimiter) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(delimiter, "delimiter"); return Delimit(@this, delimiter, x => x.ToString()); @@ -264,7 +265,7 @@ public static string Delimit(this IEnumerable @this, string delimiter) public static string Delimit(this IEnumerable @this, string delimiter, string formatString) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(delimiter, "delimiter"); Guard.NotNull(formatString, "formatString"); @@ -273,7 +274,7 @@ public static string Delimit(this IEnumerable @this, string delimiter, str public static string Delimit(this IEnumerable @this, string delimiter, Func formatter) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(delimiter, "delimiter"); Guard.NotNull(formatter, "formatter"); @@ -289,7 +290,7 @@ public static string Delimit(this IEnumerable @this, string delimiter, Fun public static IEnumerable ZipAll(this IEnumerable @this, IEnumerable other, Func, Maybe, TResult> selector) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(other, "other"); Guard.NotNull(selector, "selector"); @@ -298,7 +299,7 @@ public static IEnumerable ZipAll(this IEnumer public static IEnumerable[]> ZipAll(this IEnumerable @this, params IEnumerable[] sources) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(sources, "sources"); return ZipAll(new[] { @this }.Concat(sources)); @@ -306,13 +307,13 @@ public static IEnumerable[]> ZipAll(this IEnumerable @this, param public static IEnumerable[]> ZipAll(this IEnumerable[] @this) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); return ZipAll((IEnumerable>)@this); } public static IEnumerable[]> ZipAll(this IEnumerable> @this) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); return ZipAllCore(@this); } @@ -360,7 +361,7 @@ private static IEnumerable[]> ZipAllCore(IEnumerable> public static IEnumerable> ToZipableEnumerable(this IEnumerable @this) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); foreach (var item in @this) yield return item.ToMaybe(); @@ -371,7 +372,7 @@ public static IEnumerable> ToZipableEnumerable(this IEnumerable @ public static IEnumerable Run(this IEnumerable @this, Action action = null) { - var source = Guard.NotNull(@this, "@this"); + var source = Guard.NotNull(@this, "this"); if (action != null) source = source.OnValue(action); @@ -381,53 +382,111 @@ public static IEnumerable Run(this IEnumerable @this, Action action public static SmartLoop SmartLoop(this IEnumerable @this) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); return new SmartLoop(@this); } - public static IEnumerable Recurse(this T @this, Func> selector) + public static IEnumerable Recurse(this T @this, Func selector) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(selector, "selector"); - return new[] { @this }.Recurse(selector); + return RecurseCore(new[] {@this}, x => new[] {selector(x)}, null); } - public static IEnumerable Recurse(this IEnumerable @this, Func> selector) + public static IEnumerable RecurseWhile(this T @this, Func selector, Func predicate) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(selector, "selector"); + Guard.NotNull(predicate, "predicate"); - return @this.SelectMany(x => new[] { x }.Concat((selector(x) ?? Enumerable.Empty()).Recurse(selector))); + return RecurseCore(new[] { @this }, x => new[] { selector(x) }, predicate); } - public static IEnumerable Recurse(this T @this, Func selector) + public static IEnumerable Recurse(this T @this, Func> selector) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(selector, "selector"); - return @this.Recurse(x => selector(x).ToMaybe()); + return RecurseCore(new[] {@this}, x => selector(x).ToEnumerable(), null); } - public static IEnumerable Recurse(this T @this, Func> selector) + public static IEnumerable RecurseWhile(this T @this, Func> selector, Func predicate) + { + Guard.NotNull(@this, "this"); + Guard.NotNull(selector, "selector"); + Guard.NotNull(predicate, "predicate"); + + return RecurseCore(new[] { @this }, x => selector(x).ToEnumerable(), predicate); + } + + public static IEnumerable Recurse(this T @this, Func> selector) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(selector, "selector"); - return new[] { @this }.Concat(selector(@this).Select(x => Recurse(x, selector)).ValueOrDefault(Enumerable.Empty())); + return RecurseCore(new[] {@this}, selector, null); } + public static IEnumerable RecurseWhile(this T @this, Func> selector, Func predicate) + { + Guard.NotNull(@this, "this"); + Guard.NotNull(selector, "selector"); + Guard.NotNull(predicate, "predicate"); + + return RecurseCore(new[] { @this }, selector, predicate); + } + + public static IEnumerable Recurse(this Maybe @this, Func> selector) { Guard.NotNull(selector, "selector"); - return @this.Select(x => x.Recurse(selector)) - .ValueOrDefault(Enumerable.Empty()); + return RecurseCore(@this.ToEnumerable(), x => selector(x).ToEnumerable(), null); + } + + public static IEnumerable RecurseWhile(this Maybe @this, Func> selector, Func predicate) + { + Guard.NotNull(selector, "selector"); + Guard.NotNull(predicate, "predicate"); + + return RecurseCore(@this.ToEnumerable(), x => selector(x).ToEnumerable(), predicate); + } + + public static IEnumerable Recurse(this IEnumerable @this, Func> selector) + { + Guard.NotNull(@this, "this"); + Guard.NotNull(selector, "selector"); + + return RecurseCore(@this, selector, null); + } + + public static IEnumerable RecurseWhile(this IEnumerable @this, Func> selector, Func predicate) + { + Guard.NotNull(@this, "this"); + Guard.NotNull(selector, "selector"); + Guard.NotNull(predicate, "predicate"); + + return RecurseCore(@this, selector, predicate); + } + + private static IEnumerable RecurseCore(this IEnumerable @this, Func> selector, Func predicate) + { + + foreach (var item in @this) + { + if (item == null || (predicate != null && !predicate(item))) + continue; + + yield return item; + foreach (var child in RecurseCore(selector(item), selector, predicate)) + yield return child; + } } public static IEnumerable Squash(this IEnumerable> @this) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); return @this.Where(x => x.HasValue) .Select(x => x.Value); @@ -435,7 +494,7 @@ public static IEnumerable Squash(this IEnumerable> @this) public static IEnumerable Squash(this IEnumerable> @this) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); return @this .Where(x => x != null && x.HasValue && x.Value != null) @@ -444,7 +503,7 @@ public static IEnumerable Squash(this IEnumerable> @this) public static IEnumerable OnFirst(this IEnumerable @this, Action action) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(action, "action"); return OnFirstCore(@this, action); @@ -467,7 +526,7 @@ private static IEnumerable OnFirstCore(IEnumerable @this, Action act public static IEnumerable OnLast(this IEnumerable @this, Action action) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(action, "action"); return OnLastCore(@this, action); @@ -496,7 +555,7 @@ private static IEnumerable OnLastCore(IEnumerable @this, Action acti public static IEnumerable OnValue(this IEnumerable @this, Action action) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(action, "action"); return OnValueCore(@this, action); @@ -513,7 +572,7 @@ private static IEnumerable OnValueCore(IEnumerable @this, Action act public static IEnumerable OnNoValue(this IEnumerable @this, Action action) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(action, "action"); return OnNoValueCore(@this, action); @@ -535,7 +594,7 @@ private static IEnumerable OnNoValueCore(IEnumerable @this, Action acti public static IEnumerable OnException(this IEnumerable @this, Action action) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(action, "action"); return OnExceptionCore(@this, action); @@ -568,7 +627,7 @@ private static IEnumerable OnExceptionCore(IEnumerable @this, Action Leading(this IEnumerable @this, Action action) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(action, "action"); return LeadingCore(@this, action); @@ -584,7 +643,7 @@ private static IEnumerable LeadingCore(IEnumerable @this, Action action public static IEnumerable Finally(this IEnumerable @this, Action action) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(action, "action"); return FinallyCore(@this, action); @@ -613,7 +672,7 @@ private static IEnumerable FinallyCore(IEnumerable @this, Action action public static IEnumerable> WithNeighbors(this IEnumerable @this) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); return WithNeighborsCore(@this); } @@ -639,7 +698,7 @@ private static IEnumerable> WithNeighborsCore(this IEnumerable Or(this IEnumerable @this, IEnumerable other) { - Guard.NotNull(@this, "@this"); + Guard.NotNull(@this, "this"); Guard.NotNull(other, "other"); return OrCore(@this, other); diff --git a/Application/iSynaptic.Commons/Reflection/ReflectionExtensions.cs b/Application/iSynaptic.Commons/Reflection/ReflectionExtensions.cs index 9049223..a1b3c61 100644 --- a/Application/iSynaptic.Commons/Reflection/ReflectionExtensions.cs +++ b/Application/iSynaptic.Commons/Reflection/ReflectionExtensions.cs @@ -33,6 +33,7 @@ namespace iSynaptic.Commons.Reflection public static class ReflectionExtensions { public static IEnumerable GetAttributesOfType(this ICustomAttributeProvider provider) + where T : Attribute { return GetAttributesOfType(provider, typeof(T)) .Cast(); diff --git a/Application/iSynaptic.Commons/Reflection/TypeHierarchyComparer.cs b/Application/iSynaptic.Commons/Reflection/TypeHierarchyComparer.cs index d79c6b7..c2b3817 100644 --- a/Application/iSynaptic.Commons/Reflection/TypeHierarchyComparer.cs +++ b/Application/iSynaptic.Commons/Reflection/TypeHierarchyComparer.cs @@ -34,13 +34,13 @@ public int Compare(Type left, Type right) if (!left.IsInterface && right.IsInterface) return 1; - + int result = 0; if (left.IsAssignableFrom(right)) result--; - if (right.IsAssignableFrom(left)) + if (!left.IsAssignableFrom(right)) result++; return result; diff --git a/Application/iSynaptic.Commons/iSynaptic.Commons.csproj b/Application/iSynaptic.Commons/iSynaptic.Commons.csproj index d6815be..2d276da 100644 --- a/Application/iSynaptic.Commons/iSynaptic.Commons.csproj +++ b/Application/iSynaptic.Commons/iSynaptic.Commons.csproj @@ -75,6 +75,7 @@ + diff --git a/CommonAssemblyInfo.cs b/CommonAssemblyInfo.cs index 406054f..9d6dc4e 100644 --- a/CommonAssemblyInfo.cs +++ b/CommonAssemblyInfo.cs @@ -36,5 +36,5 @@ [assembly: ComVisible(false)] [assembly: CLSCompliant(true)] -[assembly: AssemblyVersion("0.4.14.0")] -[assembly: AssemblyFileVersion("0.4.14.0")] \ No newline at end of file +[assembly: AssemblyVersion("0.4.15.0")] +[assembly: AssemblyFileVersion("0.4.15.0")] \ No newline at end of file diff --git a/Testing/iSynaptic.Commons.UnitTests/Collections/Concurrent/ConcurrentDictionaryExtensionsTests.cs b/Testing/iSynaptic.Commons.UnitTests/Collections/Concurrent/ConcurrentDictionaryExtensionsTests.cs new file mode 100644 index 0000000..31f64a1 --- /dev/null +++ b/Testing/iSynaptic.Commons.UnitTests/Collections/Concurrent/ConcurrentDictionaryExtensionsTests.cs @@ -0,0 +1,53 @@ +// The MIT License +// +// Copyright (c) 2013 Jordan E. Terrell +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Concurrent; +using NUnit.Framework; + +namespace iSynaptic.Commons.Collections.Concurrent +{ + [TestFixture] + public class ConcurrentDictionaryExtensionsTests + { + [Test] + public void TryGetValue_ReturnsNoValue_WhenItemDoesNotExist() + { + var dict = new ConcurrentDictionary(); + var result = dict.TryGetValue("Test"); + + Assert.IsFalse(result.HasValue); + } + + [Test] + public void TryGetValue_ReturnsValue_WithItemExists() + { + var dict = new ConcurrentDictionary(); + dict.TryAdd("Test", "Hello, World!"); + + var result = dict.TryGetValue("Test"); + + Assert.IsTrue(result.HasValue); + Assert.AreEqual("Hello, World!", result.Value); + } + } +} diff --git a/Testing/iSynaptic.Commons.UnitTests/Linq/EnumerableExtensionsTests.cs b/Testing/iSynaptic.Commons.UnitTests/Linq/EnumerableExtensionsTests.cs index 41d5f80..f22a7d9 100644 --- a/Testing/iSynaptic.Commons.UnitTests/Linq/EnumerableExtensionsTests.cs +++ b/Testing/iSynaptic.Commons.UnitTests/Linq/EnumerableExtensionsTests.cs @@ -390,7 +390,7 @@ public void Batch_ViaNonGenericEnumerator_ReturnsAllItems() } [Test] - public void TestRecursivePopulationThreeLevel() + public void Recurse() { var r1 = new Recursive(1, new Recursive(2, @@ -399,10 +399,24 @@ public void TestRecursivePopulationThreeLevel() var recursives = r1.Recurse(r => r.Recursives).ToArray(); - Assert.AreEqual(4, recursives.Length); Assert.IsTrue(recursives.Select(x => x.Value).SequenceEqual(new[] { 1, 2, 4, 3 })); } + [Test] + public void RecurseWhile() + { + var r1 = new Recursive(1, + new Recursive(2, + new Recursive(4), + new Recursive(5)), + new Recursive(3, + new Recursive(6), + new Recursive(7))); + + var recursives = r1.RecurseWhile(r => r.Recursives, r => r.Value % 2 == 1).ToArray(); + Assert.IsTrue(recursives.Select(x => x.Value).SequenceEqual(new[] { 1, 3, 7 })); + } + [Test] public void Distinct_WithSelector() { @@ -718,29 +732,52 @@ public void Any_WithEnumerableBooleans_ReturnsTrueForAny() [Test] - public void All_WithEnumerableBooleans_ReturnsTrueForAll() + public void AllTrue_WithEnumerableBooleans_ReturnsTrueForAll() { - Assert.IsFalse(new[] { false, false, false }.All()); - Assert.IsFalse(new[] { false, true, false }.All()); - Assert.IsTrue(new[] { true, true, true }.All()); + Assert.IsFalse(new[] { false, false, false }.AllTrue()); + Assert.IsFalse(new[] { false, true, false }.AllTrue()); + Assert.IsTrue(new[] { true, true, true }.AllTrue()); } [Test] - public void None_WithEnumerableBooleans_ReturnsTrueForNone() + public void AllFalse_WithEnumerableBooleans_ReturnsTrueForNone() { - Assert.IsTrue(new[] { false, false, false }.None()); - Assert.IsFalse(new[] { false, true, false }.None()); - Assert.IsFalse(new[] { true, true, true }.None()); + Assert.IsTrue(new[] { false, false, false }.AllFalse()); + Assert.IsFalse(new[] { false, true, false }.AllFalse()); + Assert.IsFalse(new[] { true, true, true }.AllFalse()); } [Test] - public void None_WithSelector_ReturnsTrueForNone() + public void None_WithPredicate_ReturnsTrueForNone() { Assert.IsTrue(new[] { "false", "false", "false" }.None(bool.Parse)); Assert.IsFalse(new[] { "false", "true", "false" }.None(bool.Parse)); Assert.IsFalse(new[] { "true", "true", "true" }.None(bool.Parse)); } + [Test] + public void None_WithNoPredicate_ReturnsTrueForEmptyEnumerables() + { + Assert.IsTrue(new String[]{}.None()); + Assert.IsFalse(new [] { "Hello, World!" }.None()); + } + + [Test] + public void SelectMaybe_OnlyYieldsValuesWhereMaybeHasValue() + { + Assert.IsTrue(Enumerable.Range(1, 10) + .SelectMaybe(x => x.ToMaybe().Where(y => y % 2 == 0)) + .SequenceEqual(new[]{2,4,6,8,10})); + } + + [Test] + public void SelectMaybe_WithIndexedSelector_OnlyYieldsValuesWhereMaybeHasValue() + { + Assert.IsTrue(Enumerable.Range(1, 10) + .SelectMaybe((i, x) => x.ToMaybe().Where(y => i % 2 == 0)) + .SequenceEqual(new[] { 1, 3, 5, 7, 9 })); + } + private static IEnumerable GetRange(int start, int end, Action after) { foreach (int i in Enumerable.Range(start, end)) diff --git a/Testing/iSynaptic.Commons.UnitTests/iSynaptic.Commons.UnitTests.csproj b/Testing/iSynaptic.Commons.UnitTests/iSynaptic.Commons.UnitTests.csproj index 2b5af33..96ff4aa 100644 --- a/Testing/iSynaptic.Commons.UnitTests/iSynaptic.Commons.UnitTests.csproj +++ b/Testing/iSynaptic.Commons.UnitTests/iSynaptic.Commons.UnitTests.csproj @@ -83,6 +83,7 @@ + diff --git a/iSynaptic.Commons.ReleaseNotes.txt b/iSynaptic.Commons.ReleaseNotes.txt index e5ddf39..f635578 100644 --- a/iSynaptic.Commons.ReleaseNotes.txt +++ b/iSynaptic.Commons.ReleaseNotes.txt @@ -2,6 +2,17 @@ RELEASE NOTES: iSynaptic.Commons ====================================== +==== v0.4.15 (February 4, 2012) ==== + +---- Features ---- + +* IEnumerable extensions: added RecurseWhile overloads; renamed methods + that extend IEnumerable for clarity; improved argument validation. + +* Added TryGetValue extension method to ConcurentDictionary + that returns Maybe. + + ==== v0.4.14 (January 19, 2012) ==== ---- Features ---- diff --git a/iSynaptic.Commons.nuspec b/iSynaptic.Commons.nuspec index 20dec6f..3773db2 100644 --- a/iSynaptic.Commons.nuspec +++ b/iSynaptic.Commons.nuspec @@ -2,7 +2,7 @@ iSynaptic.Commons - 0.4.14 + 0.4.15 Jordan Terrell Library of common functionality in functional programming style. en-US