Iterating Through a Collection
Iterating Through a Collection
Enumerating a Collection
Introduction
A collection is a group of values. To create these values, you can use a collection class. you have various options.
A collection is said to be fixed if it is created (almost) once and it doesn't (or it is not supposed to) grow; that is, the number of items is not supposed to increase or decrease, you can create it as an array (as an exception, we saw that there are ways you can make an array grow or shrink). If the collection of values or objects you want to use will need many operations, you can either create a collection class or use an existing class.
Introduction to the Collections Namespaces
To use a collection, you can create a collection class. To assist you in creating and managing a collection of values or objects, the .NET Framework provides a namespace named System.Collections. The main goal of that namespace is to provide all the routine operations performed on a list of items, whether a list of primitive values or a collection of composite objects.
The System.Collections namespace contains classes used to create a collection for specific object. To allow you to create a collection for any type of object, the .NET Framework provides another namespace named System.Collections.Generics. This is a large namespace with many interfaces and various collection classes. Of course, to use a class from this namespace, if you are writing your code in a class, you either should (must) qualify the name of its class or add the namespace in the top section of the document. This can be done as follows:
using System.Collections.Generic;
public class Fundamentalist
{
}
Introduction to Collections Interfaces
To assist you to create collections, both the System.Collections and the System.Collections.Generics namespaces includes many interfaces. One of the most regular ways to check the members of a collection consists of visiting each and taking the appropriate action.
To support the ability to visit each item of a collection, the .NET Framework provides some mechanism through two interfaces named IEnumerator and IEnumerable.
Practical Learning: Introducing Iteration
namespace CountriesStatistics10.Models
{
interface IAbbreviated
{
string Abbreviation { get; set; }
}
}
namespace CountriesStatistics10.Models { interface IGovernmentEntity { string Name { get; set; } int Area { get; } string Capital { get; set; } } }
namespace CountriesStatistics10.Models { public struct Province : IAbbreviated, IGovernmentEntity { // From the IAbbreviated interface public string Abbreviation { get; set; } // From the IGovernmentEntity interface public string Name { get; set; } public string Capital { get; set; } public int Area { get { return AreaLand + AreaWater; } } // New Properties public int AreaLand { get; set; } public int AreaWater { get; set; } } }
namespace CountriesStatistics10.Controllers
{
public class Region
{
public string Designation { get; set; }
public string Description { get; set; }
}
}
using System; namespace CountriesStatistics10.Models { public class State : IAbbreviated, IGovernmentEntity, IComparable { // From the IAbbreviated interface public string Abbreviation { get; set; } // From the IGovernmentEntity interface public string Name { get; set; } public int Area { get; set; } public string Capital { get; set; } // New Properties public string StateName => Name; public int AreaSqrMiles { get; set; } public Region Region { get; set; } public int CompareTo(object stt) { if (stt == null) { return 0; } State other = stt as State; if (other != null) return StateName.CompareTo(other.StateName); return 0; } } }
using System; namespace CountriesStatistics10.Controllers { public class Federation : State { public DateTime AdmissionUnionDate { get; set; } public int AdmissionUnionOrder { get; set; } } }
body { background-image: url('../Images/background1.png'); } .navbar-inverse { background-color: #5C0700; border-bottom: 6px solid black; } .navbar-fixed-bottom { height: 60px; background-color: #5C0700; border-top: 6px solid black; } .col-md-3 { min-height: 350px; background-color: transparent; } .col-md-4 { width: 30%; } .col-md-9 { padding-left: 80px; } .row { margin-right: 0; margin-left: 0; } .jumbotron { margin-bottom: 3px; padding: 10px; background-color: #FFCC80; background-image: url('../Images/globe2.png'); } .jumbotron h1 { color: antiquewhite } .lead { color: lightgoldenrodyellow } .navbar-inverse .navbar-nav > li > a { color: #999999; } .navbar-inverse .navbar-nav > li > a:hover, .navbar-inverse .navbar-nav > li > a:focus { color: #ffffff; background: linear-gradient(#5C0700, #af8673, #5C0700); } .navbar-inverse .navbar-nav > .active > a, .navbar-inverse .navbar-nav > .active > a:hover, .navbar-inverse .navbar-nav > .active > a:focus { color: #ffffff; background-color: #080808; } .left-menu-group { list-style-type: none; } .left-menu-title { font-weight: 600; width: 100%; padding-left: 20px; margin-left: -10px; height: 1.62em; font-size: 1.55em; color: lightyellow; border-bottom: 2px solid yellow; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } .left-menu-group li { height: 1.62em; font-size: 1.35em; margin-left: -45px; padding-left: 20px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } .left-menu-group li:hover { font-size: 1.35em; border: 1px dashed maroon; background-color: antiquewhite; } .centralizer { margin: auto; width: 710px; } .tblStates { margin: auto; width: 320px; } .tblStates table { width: 100%; } .colorized { color: antiquewhite; } .country-title { font-size: 30px; font-weight: 500; line-height: 1.1; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } .tbl-header { width: 120px; border-bottom: 2px solid black; }
using System.Web.Mvc;
namespace CountriesStatistics10.Controllers
{
public class CanadaController : Controller
{
// GET: Canada
public ActionResult Index()
{
return View();
}
public ActionResult Provinces()
{
return View();
}
public ActionResult Territories()
{
return View();
}
}
}
using System.Web.Mvc;
namespace CountriesStatistics10.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
public ActionResult Continents()
{
return View();
}
public ActionResult Oceans()
{
return View();
}
public ActionResult Flags()
{
return View();
}
public ActionResult Maps()
{
return View();
}
public ActionResult Historical()
{
return View();
}
}
}
@{ ViewBag.Title = "Welcome"; ViewBag.MainTitle = "Introduction"; } <div class="jumbotron"> <div class="row"> <div class="col-md-2" style="width: 120px; height: 220px"></div> <div class="col-md-9"> <h1>Countries Statistics</h1> <p class="lead"> This is a collection of resources that will assist you in studying some of the resources that various countries of this world offer, for both academic and entertainment purposes. </p> </div> </div> </div> <hr /> <div class="row"> <div class="col-md-4"> <div class="row"> <div class="col-md-4"> <img src="~/Images/australia.png" /> </div> <div class="col-md-8"> <p class="country-title">Australia</p> </div> </div> <div class="row"> <p>This section reviews the states and territories of Australia, including some information about the government and the economy.</p> <p>@Html.ActionLink("« Learn More »", "Index", "Australia", null, new { @class = "btn btn-warning" })</p> </div> </div> <div class="col-md-4"> <div class="row"> <div class="col-md-4"> <img src="~/Images/brazil.png" /> </div> <div class="col-md-8"> <p class="country-title">Brazil</p> </div> </div> <div class="row"> <p>These are some statistics and more information about the largest and the most populous country in South America.</p> <p>@Html.ActionLink("« Learn More »", "Index", "Brazil", null, new { @class = "btn btn-warning" })</p> </div> </div> <div class="col-md-4"> <div class="row"> <div class="col-md-4"> <img src="~/Images/canada.png" /> </div> <div class="col-md-8"> <p class="country-title">Canada</p> </div> </div> <div class="row"> <p>This is one of the countries that share the world's longest border with another, its southern neighbor. Get to know Canada.</p> <p>@Html.ActionLink("« Learn More »", "Index", "Canada", null, new { @class = "btn btn-warning" })</p> </div> </div> </div> <hr /> <div class="row"> <div class="col-md-3"> <div class="row"> <div class="col-md-4"> <img src="~/Images/germany.png" /> </div> <div class="col-md-8"> <p class="country-title">Germany</p> </div> </div> <div class="row"> <p>The history, sport, geography, and politics of Germany are described in this section of our website.</p> <p>@Html.ActionLink("« Learn More »", "Index", "Germany", null, new { @class = "btn btn-warning" })</p> </div> </div> <div class="col-md-3"> <div class="row"> <div class="col-md-4"> <img src="~/Images/mexico.png" /> </div> <div class="col-md-8"> <p class="country-title">Mexico</p> </div> </div> <div class="row"> <p>Details about the Mexican states are presented, along with the tourism, culture, and entertainment.</p> <p>@Html.ActionLink("« Learn More »", "Index", "Mexico", null, new { @class = "btn btn-warning" })</p> </div> </div> <div class="col-md-3"> <div class="row"> <div class="col-md-4"> <img src="~/Images/us.png" /> </div> <div class="col-md-8"> <p class="country-title">USA</p> </div> </div> <div class="row"> <p>Review the states, territories, and other possessions of the United States, including landmarks, lakes, parks, etc.</p> <p>@Html.ActionLink("« Learn More »".ToString(), "Index", "UnitedStates", null, new { @class = "btn btn-warning" })</p> </div> </div> <div class="col-md-3"> <div class="row"> <div class="col-md-4"> <img src="~/Images/Venezuela.png" /> </div> <div class="col-md-8"> <p class="country-title">Venezuela</p> </div> </div> <div class="row"> <p>This library can help you get acquainted with Venezuela, its federal district and federal dependencies.</p> <p>@Html.ActionLink("« Learn More »".ToString(), "Index", "Venezuela", null, new { @class = "btn btn-warning" })</p> </div> </div> </div>
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Countries Statistics :: @ViewBag.Title</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") <link rel="stylesheet" type="text/css" href="~/Content/CountriesStatistics.css" /> </head> <body> <div class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> @Html.ActionLink("Countries Statistics", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" }) </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li>@Html.ActionLink("The World", "Index", "Home")</li> <li>@Html.ActionLink("Oceans", "Oceans", "Home")</li> <li>@Html.ActionLink("Continents", "Continents", "Home")</li> <li>@Html.ActionLink("Flags", "Flags", "Home")</li> <li>@Html.ActionLink("Maps", "Maps", "Home")</li> <li>@Html.ActionLink("Historical Figures", "Historical", "Home")</li> <li>@Html.ActionLink("About Us", "About", "Home")</li> <li>@Html.ActionLink("Contact Us", "Contact", "Home")</li> </ul> </div> </div> </div> <div class="container body-content"> @RenderBody() </div> <footer class="navbar-fixed-bottom"> <h4 class="text-center colorized">© @DateTime.Now.Year - Countries Statistics</h4> </footer> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
Introduction to the IEnumerator Interface
The IEnumerator<> (generic) interface provides the means of identifying the class that holds a sample of the items that will be enumerated. The IEnumerator<> interface inherits from the IEnumerator (non-generic) interface and the IDisposable (non-generic) interfaces. This means that you should include the System.Collections.Generic namespace in the top section of the document where you intend to use these interfaces. Here is an example:
using System.Collections.Generic;
To use the functionality of the IEnumerator interface, you must create a class that implements it. You can start the class as follows:
using System.Collections.Generic;
public class Enumerator<T> : IEnumerator<T>
{
}
If your collection is an array-based list, you can start by declaring the base array in the class: Here is an example:
using System.Collections.Generic;
public class Enumerator<T> : IEnumerator<T>
{
private T[] objects;
}
If the collection is not array-based, you can declare a variable for the class that would be enumerated.
The role of the enumerator is to act on a collection. For this reason, the class should be prepared to receive an external collection. This can be done by passing it to a constructor of the enumerator. Here is an example:
using System.Collections.Generic;
public class Enumerator<T> : IEnumerator<T>
{
private T[] objects;
public Enumerator(T[] list)
{
}
}
The internal collection would be used in the enumerator class. The external collection would be the source of the values of the list that would be enumerated. For these reasons, you can/should initialize the internal collection with the values of the external list. This can be done as follows:
using System.Collections.Generic;
public class Enumerator<T> : IEnumerator<T>
{
private T[] objects;
public Enumerator(T[] list)
{
this.objects = list;
}
}
Practical Learning: Introducing Enumerators
using System.Collections.Generic; namespace CountriesStatistics10.Models { public class Administrator<T> : IEnumerator<T> { private T[] organs; public Administrator(T[] list) { organs = list; } } }
The Current Item of an Enumeration
When creating a list, you should have a type of tag, as a field, that allows you to monitor the item that is being currently accessed or used in the list. The IEnumerator interface provides a property that is used to identify the current member of the list. This property is called Current. Because the current item is meant to be viewed only, the Current property is a read-only member.
To implement the Current property, you can define its get accessor to return the item at the current position. This can be done as follows:
using System.Collections.Generic; public class Enumerator<T> : IEnumerator<T> { private T[] objects; private int cur; . . . public T Current { get { return this.objects[cur]; } } }
Besides its own version, the IEnumerator<> (generic) interface inherits another version of the Current property from its parent and you must implement it too. The Current property of the IEnumerator interface is of type object. You can write its code like that of the previous version. Because both properties use the exact same name, to distinguish them, you should (must) qualify the version of the IEnumerator interface. Here is an example:
using System.Collections.Generic;
public class Enumerator<T> : IEnumerator<T>
{
. . .
object System.Collections.IEnumerator.Current
{
get
{
return this.objects[cur];
}
}
}
Practical Learning: Resetting the Tag of the Current Item
using System.Collections.Generic;
namespace CountriesStatistics10.Models
{
public class Administrator<T> : IEnumerator<T>
{
private T[] organs;
public Administrator(T[] list)
{
organs = list;
}
public T Current
{
get
{
return organs[cur];
}
}
object System.Collections.IEnumerator.Current
{
get
{
return organs[cur];
}
}
}
}
Resetting the Tag of the Current Item
Although you should be able to identify the current item at any time, when the application starts, before the collection can be enumerated, the tag that is used to monitor the current item should be set to a value before the beginning of the count. This can be done by setting the tag to -1. Here is an example:
using System.Collections.Generic;
public class Enumerator<T> : IEnumerator<T>
{
private int cur;
private T[] objects;
public Enumerator(T[] list)
{
objects = list;
cur = -1;
}
. . .
}
While the collection is being used, at one time you may want to reset the tag of the current item to its original position. To support this operation, the IEnumerator interface is equipped with a method named Reset that the IEnumerator<> interface inherits. Its syntax is:
void Reset();
When implementing this method, simply assign a non-existing value, which is usually -1, to the monitoring tag of the current item. This can be done as follows:
using System.Collections.Generic;
public class Enumerator<T> : IEnumerator<T>
{
. . .
public void Reset()
{
cur = -1;
}
}
When using the implementer of the IEnumerator<> interface, if you try accessing an item beyond the maximum number of items, the compiler would throw an IndexOutOfRangeException exception.
Practical Learning: Resetting the Tag of the Current Item
using System.Collections.Generic;
namespace CountriesStatistics10.Models
{
public class Administrator<T> : IEnumerator<T>
{
. . . No Change
public void Reset()
{
cur = -1;
}
}
}
Moving to the Next Item in the Enumerator
We know that, when using the items of a collection, one way you could locate one item from another is to jump from one item to the next. This operation is also very important when enumerating a collection. To support this operation, the IEnumerator<> interface inherits the MoveNext() method from its parent. The syntax of the IEnumerator<> interface is:
bool MoveNext();
When implementing this method, first increment the tag that monitors the current item of the collection. After incrementing the tag, check whether it is lower than the total number of items. If it is, return true. Otherwise, return false. This can be done as follows:
using System.Collections.Generic;
public class Enumerator<T> : IEnumerator<T>
{
. . .
public bool MoveNext()
{
cur++;
if (cur < objects.Length)
return true;
else
return false;
}
}
Practical Learning: Moving to the Next Item in the Enumerator
using System.Collections.Generic;
namespace CountriesStatistics10.Models
{
public class Administrator<T> : IEnumerator<T>
{
. . . No Change
public bool MoveNext()
{
cur++;
if (cur < organs.Length)
return true;
else
return false;
}
}
}
Disposing of the Enumerator
In some cases, the object of a generic class consumes resources. These resources should be freed when the object is not used anymore. To assist you with cleaning memory, the IEnumerator<> interface implements the IDisposable interface. Remember that this interface has only one method, named Dispose. If you are creating a generic class that is not concerned with resources and would let the compiler take care of that, you can simply provide a body for this method. Here is an example
using System.Collections.Generic;
public class Enumerator<T> : IEnumerator<T>
{
private int cur;
private T[] objects;
public Enumerator(T[] list)
{
cur = -1;
objects = list;
}
public T Current
{
get
{
return objects[cur];
}
}
object System.Collections.IEnumerator.Current
{
get
{
return objects[cur];
}
}
public void Reset()
{
cur = -1;
}
public bool MoveNext()
{
cur++;
if (cur < objects.Length)
return true;
else
return false;
}
public void Dispose()
{
return;
}
}
On the other hand, if you anticipate that the resources used by your class will need to be deallocated, you must implement this method properly.
Practical Learning: Disposing of the Enumerator
using System.Collections.Generic;
namespace CountriesStatistics10.Models
{
public class Administrator<T> : IEnumerator<T>
{
private int cur;
private T[] organs;
public Administrator(T[] list)
{
cur = -1;
organs = list;
}
public T Current => organs[cur];
object System.Collections.IEnumerator.Current => organs[cur];
public void Reset() => cur = -1;
public bool MoveNext()
{
cur++;
if (cur < organs.Length)
return true;
else
return false;
}
public void Dispose()
{
return;
}
}
}
Introduction
The IEnumerator<> interface is used to set up a collection for enumeration. The IEnumerator<> class doesn't provide the functionality necessary to enumerate a collection. The next step is to implement another interface called IEnumerable.
While the IEnumerator<> (generic) interface is used to identify the class that holds each value that will be visited, the IEnumerable<> (generic) interface inherits from the IEnumerator (non-generic) interface that is used to communicate with the collection whose items will be enumerated. For this reason, when implementing the IEnumerable<> interface, you should provide the means of accessing the external collection. This can be done by passing a collection of the class that holds the values, to a constructor of the IEnumerable<> implementer.
Getting the Enumerator
To implement the IEnumerable<> interface, start by deriving a class from it. While the class implemented by the IEnumerator interface represents an object, the class that implements the interface is a collection. Here is an example:
using System.Collections.Generic;
public class Collection<T> : IEnumerable<T>
{
. . . No Change
}
The new class doesn't know what collection it will be asked to enumerate. For this reason, in the new class, you should declare a member variable of the class that holds the values that will be enumerated. If the collection is array-based, we saw that you can create the field as follows:
public class Collection<T> : IEnumerable<T>
{
private T[] items;
}
Of course, you should initialize the field. Here is an example:
using System.Collections.Generic;
public class Collection<T> : IEnumerable<T>
{
private T[] items;
public Collection()
{
items = new T[10];
}
}
For a collection class, you shoud provide the routine operations such as getting the number of items in the collection. Here is an example:
using System.Collections.Generic; public class Collection<T> : IEnumerable<T> { private T[] items; private int size; public Collection() { size = 0; items = new T[10]; } public int Count { get { return size; } } }
Of course, you should also provide the ability to add items to the colloection. Here is an example:
using System.Collections.Generic;
public class Collection<T> : IEnumerable<T>
{
private T[] items;
private int size;
public Collection()
{
size = 0;
items = new T[10];
}
public int Count => size;
public void Add(T item)
{
items[size] = item;
size++;
}
}
Most importantly, you should (must) add an indexed property to the class, which we already learned how to do. Here is an example:
using System.Collections.Generic;
public class Collection<T> : IEnumerable<T>
{
private T[] items;
private int size;
public Collection()
{
size = 0;
items = new T[10];
}
public int Count
{
get
{
return size;
}
}
public void Add(T item)
{
items[size] = item;
size++;
}
public T this[int index]
{
get
{
return items[index];
}
set
{
items[index] = value;
size++;
}
}
}
Practical Learning: Starting an Enumerable Collection
using System.Collections.Generic; namespace CountriesStatistics10.Models { public class Entities<T> : IEnumerable<T> { private T[] items; private int size; public Entities() { size = 0; items = new T[10]; } public int Count => size; public void Add(T item) { items[size] = item; size++; } public T this[int index] { get { return items[index]; } set { items[index] = value; size++; } } } }
For Each Member of an Enumeration
Introduction
To support the ability to enumerate the members of a collection, the IEnumerable<> interface is equipped with a method named GetEnumerator that you must implement. The IEnumerable<>.GetEnumerator() method returns an IEnumerator<> object. Its syntax is:
IEnumerator<T> GetEnumerator();
When implementing this method, you can return an object of the class that implements the IEnumerator<> interface, passing it the collection that was declared in the IEnumerable<> implementer. This can be done as follows:
public class Collection<T> : IEnumerable<T>
{
private T[] items;
. . . No Change
public IEnumerator<T> GetEnumerator()
{
return new Enumerator<T>(items);
}
}
Besides this version, the IEnumerable<> interface inherits another version of the GetEnumerator() method from IEnumerable. Its syntax is:
IEnumerator GetEnumerator();
The IEnumerator.GetEnumerator() method returns an IEnumerator (non-generic) value. Since these two methods have the same name, to distinguish them, you must qualify the version of the IEnumerator interface. Here is an example:
using System.Collections.Generic;
public class Collection<T> : IEnumerable<T>
{
private T[] items;
private int size;
public Collection()
{
size = 0;
items = new T[10];
}
public int Count
{
get
{
return size;
}
}
public void Add(T item)
{
items[size] = item;
size++;
}
public T this[int index]
{
get
{
return items[index];
}
set
{
items[index] = value;
size++;
}
}
public IEnumerator<T> GetEnumerator()
{
return new Enumerator<T>(items);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return new Enumerator<T>(items);
}
}
Practical Learning: Introducing Each Enumeration
using System.Collections.Generic;
namespace CountriesStatistics10.Models
{
public class Entities<T> : IEnumerable<T>
{
private T[] items;
private int size;
public Entities()
{
size = 0;
items = new T[10];
}
public int Count => size;
public void Add(T item)
{
items[size] = item;
size++;
}
public T this[int index]
{
get
{
return items[index];
}
set
{
items[index] = value;
size++;
}
}
public IEnumerator<T> GetEnumerator()
{
return new Administrator<T>(items);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return new Administrator<T>(items);
}
}
}
@{ ViewBag.Title = "Canada"; } <h2>Canada</h2> @{ int i = 0; CountriesStatistics10.Models.Entities<CountriesStatistics10.Models.Province> Canada = new CountriesStatistics10.Models.Entities<CountriesStatistics10.Models.Province>(); CountriesStatistics10.Models.Province prov = new CountriesStatistics10.Models.Province(); prov.Abbreviation = "BC"; prov.Name = "British Columbia"; prov.AreaLand = 925186; prov.AreaWater = 19549; prov.Capital = "Victoria"; Canada.Add(prov); prov = new CountriesStatistics10.Models.Province(); prov.Abbreviation = "AB"; prov.Name = "Alberta"; prov.AreaLand = 642317; prov.AreaWater = 19531; prov.Capital = "Edmonton"; Canada.Add(prov); prov = new CountriesStatistics10.Models.Province() { Abbreviation = "SK", Name = "Saskatchewan", AreaLand = 591670, AreaWater = 59366, Capital = "Regina" }; Canada.Add(prov); Canada.Add(new CountriesStatistics10.Models.Province() { Abbreviation = "MB", Name = "Manitoba", AreaLand = 647797, AreaWater = 94241, Capital = "Winnipeg" }); Canada.Add(new CountriesStatistics10.Models.Province() { Abbreviation = "ON", Name = "Ontario", AreaLand = 917741, AreaWater = 158654, Capital = "Winnipeg" }); } <table border="6" style="width: 100%" cellpadding="2" cellspacing="1"> <tr> <td> </td> <td> </td> <td> </td> <td colspan="3" class="text-center"><b>Area</b></td> <td> </td> </tr> <tr> <td class="text-center"><b>#</b></td> <td class="text-center"><b>Abbrv</b></td> <td><b>Province Name</b></td> <td class="text-right"><b>Land</b></td> <td class="text-right"><b>Water<sup>2</sup></b></td> <td class="text-center"><b>Total</b></td> <td><b>Capital</b></td> </tr> @for(i = 0; i <= 4; i++) { <tr> <td class="text-center">@(i + 1)</td> <td class="text-center">@Canada[i].Abbreviation</td> <td>@Canada[i].Name</td> <td class="text-right">@Canada[i].AreaLand Km<sup>2</sup></td> <td class="text-right">@Canada[i].AreaWater Km<sup>2</sup></td> <td class="text-center">@Canada[i].Area Km<sup>2</sup></td> <td>@Canada[i].Capital</td> </tr> } </table>
Looping For Each Item in a Collection
To make it simple to enumerate the elements of a collection, the C# language provides an operator named foreach. In order to use it, the collection on which you want to apply it must implementing the IEnumerator<> and the IEnumerable<> interfaces as we have introduced in the previous sections. To start, you must prepare the collection and its items for processing. To enumerate the collection, declare a variable based on the implementer of the IEnumerable<> interface and pass the collection to its constructor. Once this is done, you can then use the foreach loop. The formula to use foreach is:
foreach(type in collection-variable) { statement(s) }
The loop starts with its keyword, followed by parentheses, and a delimited body. The type can be the class that represents the objects of the collection. Alternatively, you can use the var (or the dynamic) keyword. The collection-variable is the variable you used to create the collection. In the body of the loop, create the statement(s) you want to process. Here is an example:
<!DOCTYPE html> <html> <head> <title>Countries Statistics</title> </head> <body> <h3>Countries Statistics</h3> @{ Collection<string> territories = new Collection<string>(); territories.Add("Guam "); territories.Add("Puerto Rico"); territories.Add("United States Virgin Islands"); territories.Add("Northern Mariana Islands"); territories.Add("American Samoa"); } <h4>Territories</h4> @foreach (string strTerritory in territories) { <p>@strTerritory</p> } </body> </html>
This would produce:
In the above example, we created a collection of strings. In the same way, to create a collection of objects, pass the name of the class to the <> operator of the collection class.
Practical Learning: Looping For Each Item in a Collection
@{ ViewBag.Title = "Canada"; } <h2>Canada</h2> @{ int i = 0; CountriesStatistics10.Models.Entities<CountriesStatistics10.Models.Province> Canada = new CountriesStatistics10.Models.Entities<CountriesStatistics10.Models.Province>(); CountriesStatistics10.Models.Province prov = new CountriesStatistics10.Models.Province(); prov.Abbreviation = "BC"; prov.Name = "British Columbia"; prov.AreaLand = 925186; prov.AreaWater = 19549; prov.Capital = "Victoria"; Canada.Add(prov); prov = new CountriesStatistics10.Models.Province(); prov.Abbreviation = "AB"; prov.Name = "Alberta"; prov.AreaLand = 642317; prov.AreaWater = 19531; prov.Capital = "Edmonton"; Canada.Add(prov); prov = new CountriesStatistics10.Models.Province() { Abbreviation = "SK", Name = "Saskatchewan", AreaLand = 591670, AreaWater = 59366, Capital = "Regina" }; Canada.Add(prov); Canada.Add(new CountriesStatistics10.Models.Province() { Abbreviation = "MB", Name = "Manitoba", AreaLand = 647797, AreaWater = 94241, Capital = "Winnipeg" }); Canada.Add(new CountriesStatistics10.Models.Province() { Abbreviation = "ON", Name = "Ontario", AreaLand = 917741, AreaWater = 158654, Capital = "Winnipeg" }); Canada.Add(new CountriesStatistics10.Models.Province() { Abbreviation = "QC", Name = "Quebec", AreaLand = 1356128, AreaWater = 185928, Capital = "Quebec City" }); Canada.Add(new CountriesStatistics10.Models.Province() { Abbreviation = "NL", Name = "Newfoundland and Labrador", AreaLand = 373872, AreaWater = 31340, Capital = "St. John's" }); Canada.Add(new CountriesStatistics10.Models.Province() { Abbreviation = "PE", Name = "Prince Edward Island", AreaLand = 5660, AreaWater = 0, Capital = "Charlottetown" }); Canada.Add(new CountriesStatistics10.Models.Province() { Abbreviation = "NB", Name = "New Brunswick", AreaLand = 71450, AreaWater = 1458, Capital = "Fredericton" }); Canada.Add(new CountriesStatistics10.Models.Province() { Abbreviation = "NS", Name = "Nova Scotia", AreaLand = 53338, AreaWater = 1946, Capital = "Halifax" }); } <table border="6" style="width: 100%" cellpadding="2" cellspacing="1"> <tr> <td> </td> <td> </td> <td> </td> <td colspan="3" class="text-center"><b>Area</b></td> <td> </td> </tr> <tr> <td class="text-center"><b>#</b></td> <td class="text-center"><b>Abbrv</b></td> <td><b>Province Name</b></td> <td class="text-right"><b>Land</b></td> <td class="text-right"><b>Water</b></td> <td class="text-center"><b>Total</b></td> <td><b>Capital</b></td> </tr> @foreach(CountriesStatistics10.Models.Province prv in Canada) { <tr> <td class="text-center">@(i + 1)</td> <td class="text-center">@prv.Abbreviation</td> <td>@prv.Name</td> <td class="text-right">@prv.AreaLand Km<sup>2</sup></td> <td class="text-right">@prv.AreaWater Km<sup>2</sup></td> <td class="text-center">@prv.Area Km<sup>2</sup></td> <td>@prv.Capital</td> </tr> i++; } </table>
The IEnumerable<> interface makes it possible to enumerate the members of a collection that implements this interface. In the previous sections, we went through some details of this exercise. Because this can be overwhelming sometimes, the C# language provides the yield keyword you can use. There are various ways you can use yield.
One way you can use yield consists of creating a method that returns an IEnumerator<> value. When implementing the method, use a while loop to get to each member of the collection. In the loop, use a yield return expression to return the value that is currently visited. Also make sure you can navigate from the current to the next item, and stop when you get to the last. After creating the class, you can use it to create a collection of objects.
Practical Learning: Creating a Collection that Yields an Enumerator
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace CountriesStatistics10.Models { public class Group<T> { private T[] items; private int size; public Group() { size = 0; items = new T[10]; } public int Count { get { return size; } } public void Add(T number) { items[size] = number; size++; } public T this[int index] { get { return items[index]; } set { items[index] = value; size++; } } public IEnumerator<T> GetEnumerator() { int counter = 0; while (counter < Count) { yield return items[counter]; counter++; } } } }
namespace CountriesStatistics10.Models { public class Ocean { public string Name { get; set; } public long Area { get; set; } public long Volume { get; set; } public int AverageDepth { get; set; } public int CoastLine { get; set; } } }
@{ ViewBag.Title = "Oceans"; } <h2>World Statistics: Oceans</h2> @{ CountriesStatistics10.Models.Group<CountriesStatistics10.Models.Ocean> oceans = new CountriesStatistics10.Models.Group<CountriesStatistics10.Models.Ocean>(); CountriesStatistics10.Models.Ocean ocn = new CountriesStatistics10.Models.Ocean(); ocn.Name = "Atlantic Ocean"; ocn.Area = 85133000; ocn.Volume = 310410900; ocn.AverageDepth = 3646; ocn.CoastLine = 111866; oceans.Add(ocn); ocn = new CountriesStatistics10.Models.Ocean() { Name = "Arctic Ocean", Area = 15558000, Volume = 18750000, AverageDepth = 1205, CoastLine = 45389 }; oceans.Add(ocn); ocn = new CountriesStatistics10.Models.Ocean() { Name = "Pacific Ocean", Area = 168723000, Volume = 669880000, AverageDepth = 3970, CoastLine = 135663 }; oceans.Add(ocn); oceans.Add(new CountriesStatistics10.Models.Ocean() { Name = "Southern Ocean", Area = 21960000, Volume = 71800000, AverageDepth = 3270, CoastLine = 17968 }); oceans.Add(new CountriesStatistics10.Models.Ocean() { Name = "Indian Ocean", Area = 70560000, Volume = 264000000, AverageDepth = 3741, CoastLine = 66526 }); } <table border="4"> <tr> <td class="tbl-header"><b>Ocean</b></td> <td class="tbl-header"><b>Area</b></td> <td class="tbl-header"><b>Volume</b></td> <td class="tbl-header"><b>Avg Depth</b></td> <td class="tbl-header"><b>Coast</b></td> </tr> @foreach (CountriesStatistics10.Models.Ocean water in oceans) { <tr> <td>@water.Name</td> <td>@water.Area km<sup>2</sup></td> <td>@water.Volume km<sup>3</sup></td> <td>@water.AverageDepth meters</td> <td>@water.CoastLine km</td> </tr> } </table>
Yielding An Enumerable
Another technique to use yield consists of creating a method that returns an IEnumerable<> object. In the body of the method, you can use a while loop to access each member of the collection and return it. Once again, you combine yield and return to indicate that the method is an iterator that returns a member of the collection. At the end of each loop, find a way to get to the next member unless you have gotten to the end of the collection. As done previously, you can use a local variable to take care of that (in the following example, that local variable is named counter.
After creating the method (the code of the collection class is provided in the next Practical Learning section), when using the collection, make sure you call the method. Here is an example:
<table border="4">
<tr>
<td class="tbl-header"><b>Ocean</b></td>
<td class="tbl-header"><b>Area</b></td>
<td class="tbl-header"><b>Volume</b></td>
<td class="tbl-header"><b>Avg Depth</b></td>
<td class="tbl-header"><b>Coast</b></td>
</tr>
@foreach (CountriesStatistics10.Models.Ocean water in oceans.AllItems())
{
<tr>
<td>@water.Name</td>
<td>@water.Area km<sup>2</sup></td>
<td>@water.Volume km<sup>3</sup></td>
<td>@water.AverageDepth meters</td>
<td>@water.CoastLine km</td>
</tr>
}
</table>
You can create the method as static. In this case, you can pass the collection class as argument. When calling the method, use the name of the collection class to call the method and pass the variable as argument. Here is an example where the method is created in the body of the collection class:
using System.Collections.Generic;
public class Collection<T>
{
private T[] items;
private int size;
public Collection()
{
size = 0;
items = new T[10];
}
public int Count
{
get
{
return size;
}
}
public void Add(T number)
{
items[size] = number;
size++;
}
public T this[int index]
{
get
{
return items[index];
}
set
{
items[index] = value;
size++;
}
}
public static IEnumerable<T> AllItems(Group<T> lst)
{
int counter = 0;
while (counter < lst.Count)
{
yield return lst.items[counter];
counter++;
}
}
}
You can then call the method as follows (for a primitive type:
<!DOCTYPE html>
<html>
<head>
<title>States Statistics</title>
</head>
<body>
<h3>States Statistics</h3>
@{
Collection<string> territories = new Collection<string>();
territories.Add("Guam");
territories.Add("Puerto Rico");
territories.Add("United States Virgin Islands");
territories.Add("Northern Mariana Islands");
territories.Add("American Samoa");
}
<h4>Territories</h4>
@foreach (var strTerritory in Collection<string>.AllItems(territories))
{
<p>@strTerritory</p>
}
</body>
</html>
Here are examples for a collection of objects (for our Ocean class):
<table border="4"> <tr> <td class="tbl-header"><b>Ocean</b></td> <td class="tbl-header"><b>Area</b></td> <td class="tbl-header"><b>Volume</b></td> <td class="tbl-header"><b>Avg Depth</b></td> <td class="tbl-header"><b>Coast</b></td> </tr> @foreach (CountriesStatistics10.Models.Ocean water in CountriesStatistics10.Models.Group<CountriesStatistics10.Models.Ocean>.AllItems(oceans)) { <tr> <td>@water.Name</td> <td>@water.Area km<sup>2</sup></td> <td>@water.Volume km<sup>3</sup></td> <td>@water.AverageDepth meters</td> <td>@water.CoastLine km</td> </tr> } </table>
Practical Learning: Creating a Collection that Yields an Enumerable
namespace CountriesStatistics10.Models { public class Continent { public string Name { get; set; } public long Area { get; set; } public int HighestElevation { get; set; } public string HighestPoint { get; set; } public int LowestElevation { get; set; } public string LowestPoint { get; set; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace CountriesStatistics10.Models { public class Assembling<T> { private T[] items; private int size; public Assembling() { size = 0; items = new T[10]; } public int Count { get { return size; } } public void Add(T number) { items[size] = number; size++; } public T this[int index] { get { return items[index]; } set { items[index] = value; size++; } } public IEnumerable<T> AllItems() { int counter = 0; while (counter < Count) { yield return items[counter]; counter++; } } } }
@{ ViewBag.Title = "Continents"; } <h2>World Statistics: Continents</h2> @{ CountriesStatistics10.Models.Assembling<CountriesStatistics10.Models.Continent> continents = new CountriesStatistics10.Models.Assembling<CountriesStatistics10.Models.Continent>(); continents.Add(new CountriesStatistics10.Models.Continent() { Name = "Africa", Area = 29648481, HighestElevation = 5895, HighestPoint = "Mount Kilimanjaro (Tanzania)", LowestElevation = 155, LowestPoint = "Lake Assal (Djibouti)" }); continents.Add(new CountriesStatistics10.Models.Continent() { Name = "North America", Area = 21329926, HighestElevation = 6198, HighestPoint = "Denali (United States)", LowestElevation = 86, LowestPoint = "Death Valley (United States)" }); continents.Add(new CountriesStatistics10.Models.Continent() { Name = "South America", Area = 17461112, HighestElevation = 6960, HighestPoint = "Aconcagua (Argentina)", LowestElevation = 105, LowestPoint = "Laguna del Carbón (Argentina)" }); continents.Add(new CountriesStatistics10.Models.Continent() { Name = "Asia", Area = 31033131, HighestElevation = 8848, HighestPoint = "Mount Everest (China and Nepal)", LowestElevation = 427, LowestPoint = "Dead Sea (Israel, Jordan and Palestine)" }); continents.Add(new CountriesStatistics10.Models.Continent() { Name = "Antarctica", Area = 13720000, HighestElevation = 4892, HighestPoint = "Vinson Massif", LowestElevation = 50, LowestPoint = "Deep Lake, Vestfold Hills" }); continents.Add(new CountriesStatistics10.Models.Continent() { Name = "Australia/Oceania", Area = 8486460, HighestElevation = 4884, HighestPoint = "Puncak Jaya (Indonesia (Papua))", LowestElevation = 15, LowestPoint = "Lake Eyre (Australia)" }); continents.Add(new CountriesStatistics10.Models.Continent() { Name = "Europe", Area = 22134900, HighestElevation = 5642, HighestPoint = "Mount Elbrus (Russia)", LowestElevation = 28, LowestPoint = "Caspian Sea (Russia)" }); } <table border="4"> <tr> <td class="tbl-header"> </td> <td class="tbl-header"> </td> <td class="tbl-header text-center" colspan="2"><b>Highest Elevation</b></td> <td class="tbl-header text-center" colspan="2"><b>Lowest Elevation</b></td> </tr> <tr> <td class="tbl-header"><b>Continent</b></td> <td class="tbl-header"><b>Area</b></td> <td class="tbl-header"><b>Height</b></td> <td style="border-bottom: 2px solid black"><b>Place</b></td> <td class="tbl-header"><b>Height</b></td> <td style="border-bottom: 2px solid black"><b>Place</b></td> </tr> @foreach (CountriesStatistics10.Models.Continent place in continents.AllItems()) { <tr> <td>@place.Name</td> <td>@place.Area km<sup>2</sup></td> <td>@place.HighestElevation m</td> <td>@place.HighestPoint</td> <td>@place.LowestElevation m</td> <td>@place.LowestPoint</td> </tr> } </table>
|
||
Previous | Copyright © 2010-2019, FunctionX | Next |
|