Research on the encapsulation of foreach for iterative variables

Source: Internet
Author: User

It is well known in textbooks that the annotations in foreach are elements that cannot be altered during traversal
For example, declaring an array

int [] ii={0,1,2,3};             foreach (int in II) {                3;           the error "M" is a "foreach iteration variable" and cannot be assigned a value of                 Console.WriteLine (m);            }

As you can tell, we can't change the values inside the array, but the foreach statement is created for the collection, and the array is just one of the collections, and what about the other collections?
In C # We've created several collection classes,list<t>, arrays, and so on, and now we're using list<t> as a collection to validate our ideas, now we're going to create a type declaration as the product class.

  Public classProduct { Public intId {Set;Get; }  Public stringName {Set;Get; }  Public stringCode {Set;Get; }  PublicString Category {Get;Set; }  Public decimalPrice {Get;Set; }  PublicDateTime Productdate {Get;Set; }  Public Override stringToString () {returnString.Format ("{0}{1}{2}{3}{4}{5}", This. Id.tostring (). PadLeft (3), This. Name.padleft ( One), This. Code.padleft ( One), This. Category.padleft (7), This. Price.tostring (). PadLeft (8), This. Productdate.tostring ("yyyy-m-d"). PadLeft ( -)); }       }
View Code

In this class we rewrite the ToString method so that we can see the output better.
Now we declare an instance.

Product PR = new product ();            pr. Id = 1;            pr. Name = "Soap";            pr. Price = 1M;            pr. Productdate = DateTime.Parse ("2015-02-14");            pr. Code = "0001";            pr. Category = "Daily Necessities";

Adding a PR to the collection list

list<product> list = new list<product> ();            List. ADD (PR);

And then we traverse it.

foreach (Product PRD in list)                       {                           Console.WriteLine (PRD. ToString ());                       }

The output is

Id    trade name  Product Code   type        price     production date  0     soap    0001       daily necessities      1        2015-2-14

We're trying to iterate over the iteration variable

foreach (Product PRD in list)                       {                           Console.WriteLine (PRD. ToString ());                       }                       foreach (Product PRD in list)                       {                           PRD. Id = 2;                                                     Console.WriteLine (PRD. ToString ());                                              }

The output is

Id    trade name  Product Code   type        price     production date 0     soap    0001       daily necessities      1        2015-2-142     soap    0001       Daily Necessities      1        2015-2-14

  

The modification succeeds, the element of the iteration variable is changed successfully, we will PR at this time. ID output found that the PR ID has also been modified to 2, which is why?
We modified the PRD element not only to error, but also to change the original value. Is it because we modified the PRD. ID instead of PRD so did we succeed?
Well, let's do it again. Modify the product class to be a struct (public class product becomes public struct product). Run the above code again and find that even the compilation is not going through. The display "PRD" is a "foreach iteration variable cannot be assigned to it" ".
Now to explain the problem by analyzing the structure of the collection class, the collection class must include a public definition of "GetEnumerator" if it is to use the Foreach method, and the return value of the method is a enmerator<t> In layman's terms it's a combination class. To invoke this foreach method C # requires it to get an enumerator that is a type that he must have a bool MoveNext () method, T-current returns a property of type T, and the Void Reset () method. Every time we use the Foreach method, we call this enumerator type's method, we use the current property to return the variable of the currently iteration, because it only gets the value of the instance of product when we want to assign a value to the iteration variable, because it has only the Get method. Because we don't have a set method. But why can we modify the fields in the product class and not modify the fields in the product structure? This involves differences in memory between value types and reference types, and simply, if we have two variables on the heap, one is a value type and one is a reference type, when we make a PRD on a value type variable (that is, a struct). ID, we are now in the position of the value type instance on the heap, if we only get the value of the Get method can not be modified, but if we are a reference type, when we are the reference type instance (that is, the class) to make PRD. ID, because the reference type variable stores only one address, we PRD. The location of the ID is transferred directly to the field of the instance, not to this variable, so we use PRD. The ID is not the iteration variable, but the instance of the iteration variable is obtained.
Think about it. This is because a member of a reference type A is an instance of type a if it contains a value type member B and a reference type member C, if you want to prevent the modification of type A, instance B of type B cannot be modified because B is stored in a. And a in the reference type C instance C can be modified, because a inside stores the address of instance C, modify the content of instance C does not modify the address of instance C inside a.
The following is the code for product Collection Class Productcollection, which is from the blog of the predecessor Zhang Ziyang. We are interested to know.

#regionProduct collection type Public classProductcollection:ienumerable<product>    {        //storing product using a hash table        PrivateHashtable table; /// <summary>        ///constructor to add an instance of the product class/// </summary>        /// <param name= "Array" >Product Instance</param>         PublicProductcollection (paramsproduct[] Array) {Table=NewHashtable (); foreach(Product ppinchArray) {                 This.            ADD (PP); }        }        /// <summary>        ///Indexer/// </summary>        /// <param name= "index" ></param>        /// <returns></returns>         PublicProduct This[intIndex] {            Get             {                stringSelected =GetKey (index); returnTable[selected] asProduct; }            Set            {                stringSelected =GetKey (index); Table[selected]=value; }                  }         PublicProduct This[stringKey] {            Get{String selected=GetKey (key); returnTable[selected] asProduct; }            Set            {                stringSelected =GetKey (key); Table[selected]=value; }                   }        Private stringGetKey (intindex) {            if(Index <0|| Index >=table. Count) {Throw NewException ("Index over range! "); }            inti =0; stringSelected =""; foreach(stringIteminchtable. Keys) {if(i = =index) {Selected=item;  Break; } I++; }            returnselected; }        Private stringGetKey (stringkey) {            foreach(stringKinchtable. Keys) {if(key = = k)returnK; }            Throw NewException ("The key value does not exist"); }         Public voidAdd (Product item) {foreach(stringKeyinchtable. Keys) {if(Key = =item. Code) {Throw NewException (item. Code +"Product code cannot be duplicated"); }} table. ADD (item.        Code, item); }         Public intCount {Get            {                returntable.            Count; }        }            Public voidInsert (intindex, PRODUCT Item) {        }         Public voidRemove (Product item) {}/// <summary>        ///returns an enumerator/// </summary>        /// <returns>Enumerator</returns>         PublicIenumerator<product>GetEnumerator () {return NewProductenumerator ( This); } IEnumerator Ienumerable.getenumerator () {return NewProductenumerator ( This); }         Public classProductenumerator:ienumerator<product>        {             Public ReadOnlyproductcollection Collection; Private intindex;  PublicProductenumerator (Productcollection collection) { This. Collection =collection; Index= -1; }             PublicProduct Current {Get                {                    returnCollection[index]; }                          }            ObjectIEnumerator.Current {Get                {                    returnCollection[index]; }                          }             Public BOOLMoveNext () {index++; if(Index >=collection. Count) {return false; }                Else return true; }             Public voidReset () {index= -1; }             Public voidDispose () {}}} #endregion
View Code

Research on the encapsulation of foreach for iterative variables

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.