Yield and Singleton of C # Foundation

Source: Internet
Author: User
Tags mscorlib
1. Example analysis of the role of yiled

Recently participated in the Java pen question first see yield this keyword, since met that must master, the following is C # on the Yield keyword summary. Yield this keyword is used in the iterator block, and its most essential function is 2: one is to "sequentially" provide values to the enumeration object, and the second is to emit an iterative end signal. The corresponding statements for these two functions are yield return and yield break respectively.

Below are 2 small examples where yield and yield are not used respectively. First of all, when I debug, it is obvious that when I execute to the GetResult () method, it jumps to the inside of the method and executes, then executes the output current value statement. From the result you can see that the first is 0, indicating that the returned enumerator is located in the collection is 0, then I want to traverse the data, that is, only call MoveNext () after the enumerator will continue to move forward to get the next value, but at this time the data has been loaded into memory.

Looking at the second example, when I debug to the Getresultbyyield () method I want to enter into this method internal results found that the next sentence is directly executed, there is no entry into the Getresultbyyield () method inside. Result is found at this time. Current is null, plus the code inside the method is not executed at all, so I guess the collection is empty at this point. Continue debugging when the MoveNext () method is executed to execute Getresultbyyield () and then execute to yield return to return the value in the collection represented by the main () method output Enumerator.

You can see from the above that only the call to MoveNext () is needed to execute the method to get the result, without any results. This place the compiler will have a state machine that holds the state of the iterator to ensure that the for loop resumes execution from the last yield return stop state. This process is like the small side to drink a liter of water, if it used a one-liter cup to drink then he would like to prepare a one-liter container to fill the water dispenser filled with one liter.

If the small side can not drink half of the drink, then the rest of the water will be recycled, so whether or not to finish the drink must be prepared for a liter of water, like the first example. Now let the cup volume reduced to 0.2 liters, the small side after a cup of drink and then go to the water dispenser, drink only 0.2 liters each time. It's only when he's going to drink that he goes to fetch water, and if he doesn't drink half of it, it's obvious that the waste is more than the first way, which is like the second example. Finally, the yield return can be called to jump out of the while loop if no data is needed for the condition, and the iteration can still end normally if no yield break is written.

When no yield is used///class program {static void Main (string[] args) {//Get an iterative result            var result = GetResult (); Outputs the current value Console.WriteLine (result.            Current);            Console.WriteLine ("Start Traversal"); while (result. MoveNext ()) {Console.WriteLine (result).            Current);            } Console.WriteLine ("Traversal End");        Console.ReadLine (); }//Do not use yield to iterate static ienumeratorint> GetResult () {var arr = new int[] {1, 6, 8, 1            2,15};            listint> list = new listint> (); foreach (int item in arr) {if (item) list.            ADD (item); } return list.        GetEnumerator (); }}///////class program {static void Main (string[] args) {//Get a            Iterative results var result = Getresultbyyield ();      Output the current value      Console.WriteLine (Result.            Current);            Console.WriteLine ("Start Traversal"); while (result. MoveNext ()) {Console.WriteLine (result).            Current);            } Console.WriteLine ("Traversal End");          Console.ReadLine (); }//Use yield to iterate static IEnumerator Getresultbyyield () {var arr = new int[] {1,6,8,12,15            };                foreach (var item in arr) {yield return item;            if (item = =) yield break; }        }     }

The output results are as follows:


2. In-depth yield

Putting the second example above into the reflector tool, you get the following three pieces of code. The first paragraph is the complete C # code for the Pragrom class, the second is the C # unwind code for the D__0 sealed class, and the third is the IL Code of the Getresultbyyield () method. In the first piece of code you can see that the system automatically generates a D__0 sealed class, which declares some strange names, but we can clearly see the most important MoveNext () method and the current property in this class.

The second code is the sealed class of C # expansion code, to here do not know the reader and I had the same question: Why do you want to automatically generate a sealed class? The answer is in the third code, and you can see that the Getresultbyyield () method does not iterate through the array, or even see the newarr instruction that created the array, but newobj creates an instance object of the D__0 sealed class. This is exactly why the Getresultbyyield () method was not there at the time of debugging, because the real implementation code is in the MoveNext () method inside the sealed class. As mentioned above, yield is taken on demand, so a state machine is required to record the status of each yield return.

In the MoveNext () method, the sealed class constructor is passed in as a 0 (as you can see in the third code), so the first time you enter the MoveNext method this.__state=0. At this point the current field is NULL because it is not assigned a value. The array is then created and a while loop is started (the original foreach is the While loop), the current field is assigned a value in the loop and the State field value is 2, and finally returns true. Taking the current property is to take a while loop to assign the value of the current, again into this method when the state is equal to 2 and then jump to label_0090, that is, into the while statement block continue to loop, which is the principle of on-demand. When a yield break is encountered, the Dispose release resource is executed first, and then the break statement jumps out of the loop. Can see that this process is a state machine, and this sealed class is to build a state machine to generate, and now we can write a state machine.

Internal class program{//Methods public program ();    private static IEnumerator Getresultbyyield ();     private static void Main (string[] args);         Nested Types [compilergenerated] Private sealed class d__0:ienumeratorobject>, IEnumerator, IDisposable {        fields private int 1__state;        Private Object 2__current;        Public int[] 7__WRAP4;        public int 7__wrap5;        Public int[] 5__1;         public int 5__2;        Methods [Debuggerhidden] public d__0 (int 1__state);        private void M__finally3 ();        private bool MoveNext ();        [Debuggerhidden] void Ienumerator.reset ();         void IDisposable.Dispose (); Properties object Ienumeratorobject>.        Current {[Debuggerhidden] get;}    Object IEnumerator.Current {[Debuggerhidden] get;}    }}private sealed class D__0:ienumeratorobject>, IEnumerator, idisposable{//fields private int 1__state; Private Object 2__curRent    Public int[] 7__WRAP4;    public int 7__wrap5;    Public int[] 5__1;     public int 5__2;    Methods [Debuggerhidden] public d__0 (int 1__state) {this.1__state = 1__state;    } private void M__finally3 () {this.1__state =-1; } private bool MoveNext () {try {switch (this.1__state) {case                    0:this.1__state =-1;                    This.5__1 = new int[] {1, 6, 8, 12, 15};                    This.1__state = 1;                    THIS.7__WRAP4 = this.5__1;                    THIS.7__WRAP5 = 0; while (THIS.7__WRAP5 THIS.7__WRAP4.                        Length) {this.5__2 = THIS.7__WRAP4[THIS.7__WRAP5];                        This.2__current = this.5__2;                        This.1__state = 2;                    return true;                        Label_0090:this.1__state = 1; if (thiS.5__2 = =) {this.                            System.IDisposable.Dispose ();                        Break                    } this.7__wrap5++;                    } this.m__finally3 ();                 Break            Case 2:goto label_0090;        } return false; } fault {this.        System.IDisposable.Dispose ();    }} [Debuggerhidden] void Ienumerator.reset () {throw new NotSupportedException ();                } void IDisposable.Dispose () {switch (this.1__state) {Case 1:case 2:                This.m__finally3 ();        Break }}//Properties object Ienumeratorobject>.        Current {[Debuggerhidden] get {return this.2__current;     }} object IEnumerator.Current {[Debuggerhidden] get {       return this.2__current;    }}}. method private Hidebysig static class [Mscorlib]system.collections.ienumerator Getresultbyyield () CIL managed  {. maxstack 1. Locals init ([0] class Consoleapplication1.program/d__0 d__, [1] class [mscorlib] System.Collections.IEnumerator enumerator) l_0000:ldc.i4.0 l_0001:newobj instance void ConsoleApplication1 .         Program/d__0::.ctor (Int32) l_0006:stloc.0 l_0007:ldloc.0 l_0008:stloc.1 l_0009:br.s l_000b L_000b:ldloc.1 L_000c:ret}

3. Single-Case mode

Singleton mode There is nothing to say, of course, if deep digging should also be a lot of knowledge, which I think is better than one of the following. The code of the singleton mode I have seen many times but not how to write, the result is really written when the time and a little tight last write a mess. Later write code to xingping gas and ground to write, impatient state write no good code. Of course there will always be irritability, so you can only write more code to let yourself write high-quality code become a habit!

Class A    {        private static A instance = new A ();        public static A Instance        {            get {return a.instance;}        }    }

Above is the C # basis of yield and singleton content, more relevant content please pay attention to topic.alibabacloud.com (www.php.cn)!

  • 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.