C # uses Ienumerable,yield to return results, while using foreach, modifying the value of a variable within a loop is not valid

Source: Internet
Author: User

A strange problem was encountered in the project, which did not take effect when the value of the list was modified in the Foreach loop, or when it was used to get the list, because the yield return . Let's explore the reasons below:

First, take a look at the official explanation of yield return.

Use the yield return statement to return one element at a time.
Use the iterator method with a foreach statement or a LINQ query. Each iteration of the Foreach loop invokes an iterator method. When the iterator method runs to the yield return statement, it returns an expression and retains the current position in the code. The next time the iterator function is called, execution restarts from that location.

var list = GetEnumerable(); //此时并不会执行GetEnumerable()foreach (var test in list) //1|4|7 当执行到in时才会进入GetEnumerable()方法{    test.atr1 = 0;//3|6|9}public IEnumerable<ListTest> GetEnumerable(){    for (int i = 0; i < 2; i++)    {        yield return new ListTest()        {            atr1 = i + 1        };//2|5|8    }}

As you can see from the code above, the code is actually executed to get the variable when it is actually used in the list.
The next feature of yield return is the reason for modifying the value of the variable in the loop:

 var list = getenumerable (); Getenumerable () foreach (var test in list) is not executed at this time//1|4|7 enters Getenumerable () method {test.atr1 = 0;//3|6|9}foreach when executing into in (var test in list)//10|13|16{TEST.ATR1 = 0;//12| | 15|18}public ienumerable<listtest> getenumerable () {for (int i = 0; i < 2; i++) {yield return new L Isttest () {atr1 = i + 1};//2|5|8| 11|14|17}}  

Here we can actually think of another problem, that is, the function has a relatively time-consuming operation and the function calls the place to use the return of the results, this will greatly affect performance, the following is an experiment:

 stopwatch watch = new Stopwatch (); watch. Start (); var list = getenumerable (); for (int i = 0; i <; i++) {list. ToList ().               ForEach (o = Console.Write (o.atr1)); }watch. Stop (); Console.WriteLine ("Spend time:" + watch.) elapsedmilliseconds);p ublic ienumerable<listtest> getenumerable () {thread.sleep (10);//Add this step for a longer period of time to make the effect more obvious for    (int i = 0; i < 2; i++)    {yield return new listtest () {atr1 = i + 1}; }}

The following is the time the function was executed:

So many times the use of time-consuming performance.
If we don't want this effect, how to solve it?
One method is to not yield return, and one method is to convert it to a list when it gets the return result:

var list = GetEnumerable().ToList();

Let's look at the time:

The use of this function is done only once, which can save a lot of performance, and can also solve the problem of changing the value of variables in the loop .
MSDN's explanation of yield is as follows;

Use the yield keyword in a statement to indicate that the method, operator, or get accessor where the keyword is located is an iterator. By using the yield definition iterator, you can implement the IEnumerable and IEnumerator modes of a custom collection type without additional explicit classes.

The purpose of yield is to make it easier to use iterators, which are useful when the returned results are used only once.

?

C # uses Ienumerable,yield to return results, while using foreach, modifying the value of a variable within a loop is not valid

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.