近期收集一些基于IEnumerable<T>扩展方法,它给我们带了很多便利,有时的确是实用的。其中有Alternate,Append,Prepend,Distinct,Contains。具体怎么用呢
Code:
/// <summary>
/// IEnumerableExtension
/// </summary>
public static class IEnumerableExtensions
{
#region Methods (5)
// Public Methods (5)
/// <summary>
/// Alternates the specified first.
/// </summary>
/// <typeparam name="TSource">The type of the source.</typeparam>
/// <param name="first">The first.</param>
/// <param name="second">The second.</param>
/// <returns></returns>
public static IEnumerable<TSource> Alternate<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
{
using (IEnumerator<TSource> e1 = first.GetEnumerator())
using (IEnumerator<TSource> e2 = second.GetEnumerator())
while (e1.MoveNext() && e2.MoveNext())
{
yield return e1.Current;
yield return e2.Current;
}
}
/// <summary>
/// Appends the specified source.
/// </summary>
/// <typeparam name="TSource">The type of the source.</typeparam>
/// <param name="source">The source.</param>
/// <param name="element">The element.</param>
/// <returns>IEnumerable<TSource></returns>
public static IEnumerable<TSource> Append<TSource>(this IEnumerable<TSource> source, TSource element)
{
using (IEnumerator<TSource> e1 = source.GetEnumerator())
while (e1.MoveNext())
yield return e1.Current;
yield return element;
}
/// <summary>
/// Determines whether [contains] [the specified source].
/// </summary>
/// <typeparam name="TSource">The type of the source.</typeparam>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="source">The source.</param>
/// <param name="value">The value.</param>
/// <param name="selector">The selector.</param>
/// <returns>
/// <c>true</c> if [contains] [the specified source]; otherwise, <c>false</c>.
/// </returns>
public static bool Contains<TSource, TResult>(
this IEnumerable<TSource> source, TResult value, Func<TSource, TResult> selector)
{
foreach (TSource sourceItem in source)
{
TResult sourceValue = selector(sourceItem);
if (sourceValue.Equals(value))
return true;
}
return false;
}
/// <summary>
/// Distincts the specified source.
/// </summary>
/// <typeparam name="TSource">The type of the source.</typeparam>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="source">The source.</param>
/// <param name="comparer">The comparer.</param>
/// <returns>IEnumerable<TSource></returns>
public static IEnumerable<TSource> Distinct<TSource, TResult>(
this IEnumerable<TSource> source, Func<TSource, TResult> comparer)
{
return source.Distinct(new DynamicComparer<TSource, TResult>(comparer));
}
/// <summary>
/// Prepends the specified source.
/// </summary>
/// <typeparam name="TSource">The type of the source.</typeparam>
/// <param name="source">The source.</param>
/// <param name="element">The element.</param>
/// <returns>IEnumerable<TSource></returns>
public static IEnumerable<TSource> Prepend<TSource>(this IEnumerable<TSource> source, TSource element)
{
yield return element;
using (IEnumerator<TSource> e1 = source.GetEnumerator())
while (e1.MoveNext())
yield return e1.Current;
}
#endregion Methods
}
/// <summary>
/// DynamicComparer
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TResult">The type of the result.</typeparam>
public class DynamicComparer<T, TResult> : IEqualityComparer<T>
{
#region Fields (1)
private readonly Func<T, TResult> _selector;
#endregion Fields
#region Constructors (1)
/// <summary>
/// Initializes a new instance of the <see cref="DynamicComparer<T, TResult>"/> class.
/// </summary>
/// <param name="selector">The selector.</param>
public DynamicComparer(Func<T, TResult> selector)
{
_selector = selector;
}
#endregion Constructors
#region Methods (2)
// Public Methods (2)
/// <summary>
/// Determines whether the specified objects are equal.
/// </summary>
/// <param name="x">The first object of type <paramref name="T"/> to compare.</param>
/// <param name="y">The second object of type <paramref name="T"/> to compare.</param>
/// <returns>
/// true if the specified objects are equal; otherwise, false.
/// </returns>
public bool Equals(T x, T y)
{
TResult result1 = _selector(x);
TResult result2 = _selector(y);
return result1.Equals(result2);
}
/// <summary>
/// Returns a hash code for the specified object.
/// </summary>
/// <param name="obj">The <see cref="T:System.Object"/> for which a hash code is to be returned.</param>
/// <returns>A hash code for the specified object.</returns>
/// <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(T obj)
{
TResult result = _selector(obj);
return result.GetHashCode();
}
#endregion Methods
}
UnitTest:
1: #region Methods (8)
2:
3: // Public Methods (7)
4:
5: [Test]
6: public void Bad_concat_method()
7: {
8: var ints = new[] { 1, 2, 3 };
9:
10: var oneToFour = ints.Concat(Enumerable.Repeat(4, 1));
11:
12: CollectionAssert.AreEqual(new[] { 1, 2, 3, 4 }, oneToFour.ToArray());
13: }
14:
15: [Test]
16: public void Better_enumerable_extensions()
17: {
18: var values = new[]
19: {
20: new Person {FirstName = "Bob", LastName = "Smith"},
21: new Person {FirstName = "Don", LastName = "Allen"},
22: new Person {FirstName = "Bob", LastName = "Sacamano"},
23: new Person {FirstName = "Chris", LastName = "Smith"},
24: new Person {FirstName = "George", LastName = "Allen"}
25: };
26:
27: Assert.AreEqual(3, values.Distinct(person => person.LastName).Count());
28: Assert.AreEqual(4, values.Distinct(person => person.FirstName).Count());
29: Assert.IsTrue(values.Contains("Smith", person => person.LastName));
30: Assert.IsFalse(values.Contains("Nixon", person => person.LastName));
31: }
32:
33: [Test]
34: public void Easier_concat_with_append()
35: {
36: var ints = new[] { 1, 2, 3 };
37:
38: var oneToFour = ints.Append(4);
39:
40: CollectionAssert.AreEqual(new[] { 1, 2, 3, 4 }, oneToFour.ToArray());
41: }
42:
43: [Test]
44: public void Easier_concat_with_prepend()
45: {
46: var ints = new[] { 1, 2, 3 };
47:
48: var zeroToThree = ints.Prepend(0);
49:
50: CollectionAssert.AreEqual(new[] { 0, 1, 2, 3 }, zeroToThree.ToArray());
51: }
52:
53: [Test]
54: public void TestAggregate()
55: {
56: string sentence = "the quick brown fox jumps over the lazy dog";
57:
58: // Split the string into individual words.
59: string[] words = sentence.Split(' ');
60:
61: // Prepend each word to the beginning of the
62: // new sentence to reverse the word order.
63: string reversed = words.Aggregate((workingSentence, next) =>
64: next + " " + workingSentence);
65: Assert.AreEqual("dog lazy the over jumps fox brown quick the",reversed);
66: }
67:
68: [Test]
69: public void TestintArray()
70: {
71: int[] aa = new int[] { 1, 3, 5};
72: int[] bb = new int[] { 2, 4, 6 };
73:
74: var cc = aa.Alternate(bb);
75:
76: CollectionAssert.AreEqual(new[] { 1, 2, 3, 4, 5, 6},cc.ToArray());
77:
78: }
79:
80: [Test]
81: public void Word_play()
82: {
83: var source = new[] { "That", "is", "exactly", "I", "want" };
84:
85: var result = source.Alternate(Spaces()).Aggregate(string.Empty, (a, b) => a + b);
86:
87:
88: foreach (var s in result)
89: {
90: Console.Write(s);
91: }
92: //That is exactly I want
93: }
94: // Private Methods (1)
95:
96: private IEnumerable<string> Spaces()
97: {
98: while (true)
99: yield return " ";
100: }
101:
102: #endregion Methods
Author:Petter Liu http://wintersun.cnblogs.com