近期收集一些基于IEnumerable<T>扩展方法,它给我们带了很多便利,有时的确是实用的。其中有Alternate,Append,Prepend,Distinct,Contains。具体怎么用呢,看下面的UnitTest.

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&lt;T, TResult&gt;"/> 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  

希望这篇Post对您有帮助。

posted on 2009-11-06 16:57  PetterLiu  阅读(3119)  评论(0编辑  收藏  举报