Understand IEnumerable Let's talk about IEnumerable first, do you really understand the foreach we use every day? Detailed explanation of the principle of c# yield keyword

First I read a great blog

Let's talk about IEnumerable first, do you really understand the foreach we use every day?

This is a more comprehensive introduction to the use of iterators, and a good answer to the three questions raised by the blogger himself. Then here are some of my own conclusions

 

Why can't the value of item be modified in foreach?

The answer is that the object Current of IEnumerator has only the get method, and the IEnumerator returned by Collection exposes the current property as a read-only property, so its modification will cause a runtime error.

At first, I was still wondering if I could implement the set method. After trying a few times, I found that I was stupid. This should be deliberately designed so that the value cannot be modified. If you really want to modify the value, you just need to change the foreach to for to traverse it. .

 

What is the yield keyword?

  1. is syntactic sugar to simplify the implementation of traversal operations
  2. 有yield retrun和yield break
  3. Can only be used in methods, operators, get accessors whose return type must be IEnumerable, IEnumerable<T>, IEnumerator, or IEnumerator<T>

As a syntactic sugar, yield only reduces the amount of code, and the final implementation is still implemented through the interface.

Details can be found here: Detailed explanation of the principle of c# yield keyword

 

 

Finally, mark this IEnumerable random value method (source "In-depth Understanding of C#"), it's really amazing

    // Random value 
    public  static  class RandomValue
    {
        public static T RandomEnumerableValue<T>(this IEnumerable<T> source, Random random)
        {
            if (source == null)
                throw new ArgumentNullException("sourcce");
            if (random == null)
                throw new ArgumentNullException("random");

            if (source is ICollection)
            {
                ICollection collection = source as ICollection;
                int count = collection.Count;
                if (count == 0)
                {
                    throw  new Exception( " IEnumerable has no data " );
                }
                int index = random.Next(count);
                return source.ElementAt(index);
            }

            using (IEnumerator<T> iterator = source.GetEnumerator())
            {
                if (!iterator.MoveNext())
                {
                    throw  new Exception( " IEnumerable has no data " );
                }
                int count = 1;
                T current = iterator.Current;
                while (iterator.MoveNext())
                {
                    count++;
                    if (random.Next(count) == 0)
                        current = iterator.Current;
                }
                return current;
            }
        }
    }

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325208067&siteId=291194637