Indexers and Classes
Indexers and Classes
Fundamentals of Indexed Properties and Classes
Introduction
Just as done for primitive types, you can create an indexer that is of a class type. For example, you can create a class so that one of its fields declared as an array can be accessed with an index directly applied to an instance of the class.
Practical Learning: Introducing Indexers and Classes
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MetroSystem11.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 Emergencies()
{
return View();
}
public ActionResult Stations()
{
return View();
}
public ActionResult StationSearch()
{
return View();
}
public ActionResult Lines()
{
return View();
}
}
}
body { background-color: #686666; } .container { background-color: #FFFFFF; } .top-group { background-color: #FFFFFF; border-bottom: 4px solid #000000; } .bottom-group { background-color: #000000; border-top: 4px solid #ffffff; } .top-group .navbar-nav > li > a { color: #0c47c1; } .top-group .navbar-nav > li > a:hover, .top-group .navbar-nav > li > a:focus { color: #ffffff; background-color: #0c47c1; } .top-group .navbar-nav > .active > a, .top-group .navbar-nav > .active > a:hover, .top-group .navbar-nav > .active > a:focus { color: #ffffff; background-color: #080808; } .copy-holder { margin-top: 15px; color: #00ffff; } .metro-pic { height: 300px; padding-top: 120px; text-align: center; background-position: center; border-bottom: 2px solid #000000; background-image: url('../Images/mts3.jpg'); } .jumbotron { margin-bottom: 40px; margin-left: 0; } .jumbotron h1 { line-height: 1; color: #ffd800; } .container .jumbotron { border-radius: 1px; } @media screen and (min-width: 768px) { .jumbotron h1 { font-size: 63px; } .jumbotron { padding-top: 85px; } .container .jumbotron { margin-right: -15px; margin-left: -15px; } } .btn-info { color: #ffffff; background-color: #0c47c1; border-color: #000000; } .btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info { color: #ffffff; background-color: #39b3d7; border-color: #000000; } .btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info { background-image: none; }
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Metropolitan Transit System :: @ViewBag.Title</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") <link rel="stylesheet" type="text/css" href="~/Content/MetroSystem.css" /> </head> <body> <div class="navbar top-group 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> <div><img src="~/Images/mts1.png" alt="Metropolitan Transit System" width="172" height="50" /></div> </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav navbar-right"> <li>@Html.ActionLink("MTS Home", "Index", "Home")</li> <li>@Html.ActionLink("Stations", "Stations", "Home")</li> <li>@Html.ActionLink("Metro Lines", "About", "Home")</li> <li>@Html.ActionLink("Need Help?", "About", "Home")</li> <li>@Html.ActionLink("About MTS", "About", "Home")</li> <li>@Html.ActionLink("Contacts", "Contact", "Home")</li> </ul> </div> </div> </div> <div class="container body-content"> @RenderBody() <hr /> </div> <footer class="navbar bottom-group navbar-fixed-bottom"> <div class="copy-holder"> <p class="text-center">© @DateTime.Now.Year - Metropolitan Transit System -</p> </div> </footer> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
@{ ViewBag.Title = "Introduction"; } <div class="jumbotron metro-pic"> <h1>Metropolitan Transit System</h1> <p class="lead"> </p> <p class="lead"> </p> <p><a href="https://asp.net" class="btn btn-info btn-lg">Learn more »</a></p> </div> <div class="row"> <div class="col-md-3"> <p class="text-center"><img src="~/Images/planning.png" alt="Planning and Designing for the Future" width="77" height="77" /></p> <h2 class="text-center">Emergencies</h2> <p>MTS closely monitors unusual situations (including weather conditions) and notifies the community.</p> <p class="text-center"><a class="btn btn-info" href="https://go.microsoft.com/fwlink/?LinkId=301865">Learn more »</a></p> </div> <div class="col-md-3"> <p class="text-center"><img src="~/Images/line.png" alt="Metro Lines" width="74" height="84" /></p> <h2 class="text-center">Careers</h2> <p>Join the MTS team for a challenging career and tremendous possibilities of advancement.</p> <p class="text-center"><a class="btn btn-info" href="https://go.microsoft.com/fwlink/?LinkId=301866">Learn more »</a></p> </div> <div class="col-md-3"> <p class="text-center"><img src="~/Images/map.png" alt="Color and Black and White Maps" width="71" height="84" /></p> <h2 class="text-center">Maps</h2> <p>Metro lines intersect and share many characteristics. You can see the maps of transit lines here.</p> <p class="text-center"><a class="btn btn-info" href="https://go.microsoft.com/fwlink/?LinkId=301867">Learn more »</a></p> </div> <div class="col-md-3"> <p class="text-center"><img src="~/Images/station.png" alt="Metro Stations" width="75" height="79" /></p> <h2 class="text-center">Training</h2> <p>MTS offers various types of training programs for both employees and contractors.</p> <p class="text-center"><a class="btn btn-info" href="https://go.microsoft.com/fwlink/?LinkId=301867">Learn more »</a></p> </div> </div>
An Integer-Based Indexed Property
Before designing an indexer that is class-based, first create the class that will be used as the data type. The class can be simple or complex as you judge it necessary.
Practical Learning: Using an Integer-Based Indexer
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MetropolitanTransicSystem1.Models { public class MetroStation { public string Name { get; set; } public string Location { get; set; } public MetroStation() { Name = "Unknown"; Location = "Unknown"; } public MetroStation(string name, string address) { Name = name; Location = address; } public override string ToString() { return $"{Name} ({Location})"; } } }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MetropolitanTransicSystem1.Models
{
public class MetroStation
{
public string Name { get; set; }
public string Location { get; set; }
public MetroStation(string name, string address)
{
Name = name;
Location = address;
}
}
public class Stations
{
private MetroStation[] stations;
public MetroStation this[int i]
{
get
{
return stations[i];
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MetropolitanTransicSystem1.Models
{
public class MetroStation
{
public string Name { get; set; }
public string Location { get; set; }
public MetroStation()
{
Name = "Unknown";
Location = "Unknown";
}
public MetroStation(string name, string address)
{
Name = name;
Location = address;
}
public override string ToString()
{
return $"{Name} ({Location})";
}
}
public class Stations
{
private MetroStation[] stations;
public Stations()
{
stations = new MetroStation[20];
stations[0] = new MetroStation("Shady Grove", "Rockville");
stations[1] = new MetroStation("Rockville", "Rockville");
stations[2] = new MetroStation("Twinbrook", "Rockville");
stations[3] = new MetroStation("White Flint", "Rockville");
stations[4] = new MetroStation("Grosvenor - Strathmore", "Bethesda");
stations[5] = new MetroStation("Medical Center", "Bethesda");
stations[6] = new MetroStation("Bethesda", "Bethesda");
stations[7] = new MetroStation("Friendship Heights", "DC");
stations[8] = new MetroStation("Tenleytown - AU", "DC");
stations[9] = new MetroStation("Van Ness -UDC", "DC");
stations[10] = new MetroStation("Cleveland Park", "DC");
stations[11] = new MetroStation("Woodley Park - Zoo / Adams Morgan", "DC");
stations[12] = new MetroStation("Dupont Circle", "DC");
stations[13] = new MetroStation("Farragut North", "DC");
stations[14] = new MetroStation("Metro Center", "DC");
stations[15] = new MetroStation("Gallery Pl - Chinatown", "DC");
stations[16] = new MetroStation("Judiciary Square", "DC");
stations[17] = new MetroStation("Union Station", "DC");
stations[18] = new MetroStation("NoMa - Gallaudet University", "DC");
stations[19] = new MetroStation("Rhode Island Ave - Brentwood", "DC");
stations[20] = new MetroStation("Brookland - CUA", "DC");
stations[21] = new MetroStation("Fort Totten", "DC");
stations[22] = new MetroStation("Takoma", "DC");
stations[23] = new MetroStation("Silver Spring", "Silver Spring");
stations[24] = new MetroStation("Forest Glen", "Silver Spring");
stations[25] = new MetroStation("Wheaton", "Silver Spring");
stations[26] = new MetroStation("Glenmont", "Silver Spring");
}
public MetroStation this[int i]
{
get
{
return stations[i];
}
}
}
}
@{ ViewBag.Title = "Metro Stations"; var metro = new MetropolitanTransicSystem1.Models.Stations(); } <h2>Metro Stations</h2> <table> <tr> <td><h3>Stations</h3></td> </tr> @for(int i = 0; i < 20; i++) { <tr> <td>@metro[i]</td> </tr> } </table>
An Indexed Property Using Another Primitive Type
As done for primitive types, an indexer can take a parameter other than the regular integer. For example, you can use a Boolean type or another type of integer.By now, we know that a basic indexed property produces (or all the indexed properties we have studied so far produce) only one value. If you have a class that has only one field, this would be enough. Most of the time, a class has many fields. In such a case, when you create an indexer , you need to be able to refer to one exact element of the array. To make this possible, you must define a way to point to the particular element you want. One way you can do this is to use one field of the class as a reference. You can start the property as follows:
public class SchoolRegistration
{
Student[] std = new Student[5];
public Student this[long id]
{
}
}
To use such a property, you must provide a value that uniquely identifies an element of the array. When you get such a value, you can search for it in the array. If you find it and the array has a get accessor, you can then return the desired but appropriate value. Here is a way this can be done:
public class SchoolRegistration
{
Student[] students = new Student[50];
public Student this[long id]
{
get
{
for (int i = 0; i < students.Length; i++)
{
if (students[i].StudentID == id)
return students[i];
}
// Unknown student or the number was not found
return null;
}
}
}
Practical Learning: Creating a Short Integer-Based Indexed Property
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MetropolitanTransicSystem1.Models { public class MetroStation { public short StationNumber { get; set; } public string Name { get; set; } public string Location { get; set; } public bool Parking { get; set; } public int BikeRacks { get; set; } public MetroStation() { StationNumber = 0; Name = "Unknown"; Location = "Unknown"; Parking = false; BikeRacks = 0; } public MetroStation(short id, string name, string address, bool parking, int bike) { StationNumber = id; Name = name; Location = address; Parking = parking; BikeRacks = 0; } public override string ToString() { return $"{Name} ({StationNumber}, {Location})"; } } public class Stations { private MetroStation[] stations; public Stations() { stations = new MetroStation[20]; stations[0] = new MetroStation(2014, "Shady Grove", "Rockville", true, 32); stations[1] = new MetroStation(1660, "Rockville", "Rockville", true, 69); stations[2] = new MetroStation(9722, "Twinbrook", "Rockville", true, 68); stations[3] = new MetroStation(9722, "White Flint", "Rockville", true, 32); stations[4] = new MetroStation(8294, "Grosvenor - Strathmore", "Bethesda", true, 40); stations[5] = new MetroStation(2864, "Medical Center", "Bethesda", true, 88); stations[6] = new MetroStation(2814, "Bethesda", "Bethesda", false, 48); stations[7] = new MetroStation(9204, "Friendship Heights", "DC", false, 50); stations[8] = new MetroStation(8648, "Tenleytown - AU", "DC", false, 20); stations[9] = new MetroStation(2522, "Van Ness - UDC", "DC", false, 9); stations[10] = new MetroStation(9741, "Cleveland Park", "DC", false, 16); stations[11] = new MetroStation(1626, "Woodley Park - Zoo / Adams Morgan", "DC", false, 8); stations[12] = new MetroStation(9279, "Dupont Circle", "DC", false, 16); stations[13] = new MetroStation(7974, "Farragut North", "DC", false, 16); stations[14] = new MetroStation(9294, "Metro Center", "DC", false, 8); stations[15] = new MetroStation(1359, "Gallery Place - Chinatown", "DC", false, 0); stations[16] = new MetroStation(8200, "Judiciary Square", "DC", false, 18); stations[17] = new MetroStation(1802, "Union Station", "DC", false, 23); stations[18] = new MetroStation(2014, "NoMa - Gallaudet University", "DC", false, 10); stations[19] = new MetroStation(1116, "Rhode Island Ave - Brentwood", "DC", true, 12); stations[20] = new MetroStation(3948, "Brookland - CUA", "DC", false, 10); stations[21] = new MetroStation(9794, "Fort Totten", "DC", true, 10); stations[22] = new MetroStation(8270, "Takoma", "DC", false, 38); stations[23] = new MetroStation(9274, "Silver Spring", "Silver Spring", false, 26); stations[24] = new MetroStation(1417, "Forest Glen", "Silver Spring", true, 42); stations[25] = new MetroStation(9737, "Wheaton", "Silver Spring", true, 36); stations[26] = new MetroStation(8802, "Glenmont", "Silver Spring", true, 36); } public MetroStation this[short number] { get { for(int i = 0; i < stations.Length - 1; i++) { if(stations[i].StationNumber == number) { return stations[i]; } } return new MetroStation(); } } } }
@{ ViewBag.Title = "Station Search"; MetropolitanTransicSystem1.Models.Stations stations = new MetropolitanTransicSystem1.Models.Stations(); } <h2>Station Search</h2> @{ int bikeRacks = 0; short stationID = 0; bool parkingAvailable = false; string strLocation = string.Empty; string strStationName = string.Empty; if (IsPost) { stationID = Convert.ToInt16(Request["txtStationNumber"]); strStationName = stations[stationID].Name; strLocation = stations[stationID].Location; parkingAvailable = stations[stationID].Parking; bikeRacks = stations[stationID].BikeRacks; } } @using (Html.BeginForm()) { <table> <tr> <td>Enter Station #:</td> <td>@Html.TextBox("txtStationNumber", @stationID, new { style = "width: 50px" }) <input type="submit" name="btnFind" value="Find" /></td> </tr> <tr> <td>Station Name:</td> <td>@Html.TextBox("txtStationName", @strStationName)</td> </tr> <tr> <td>Location:</td> <td>@Html.TextBox("txtLocation", @strLocation)</td> </tr> <tr> <td>Parking Available:</td> <td>@Html.TextBox("txtParkingAvailable", @parkingAvailable)</td> </tr> <tr> <td>Number of Bike Racks:</td> <td>@Html.TextBox("txtBikeRacks", @bikeRacks)</td> </tr> </table> }
Topics on Indexed Properties and Classes
A Class as Index
As opposed to returning a class, an indexer can use a class as its index. Here is a class to start with:
public class MetroStation { public bool Parking { get; set; } public int BikeRacks { get; set; } public string LineName { get; set; } public string Location { get; set; } public string StationName { get; set; } public short StationNumber { get; set; } public MetroStation(short id) { BikeRacks = id; } public MetroStation(short id, string station, string address, string lName) { StationNumber = id; StationName = station; Location = address; LineName = lName; } public MetroStation(short id, string station, string address, bool parking, int bike, string lName) { StationNumber = id; StationName = station; Location = address; Parking = parking; BikeRacks = 0; LineName = lName; } public override string ToString() { return $"{StationName} (#{StationNumber}, in {Location})"; } }
To create an indexed property that uses an object as index, the primary action you must take is to include a class and its name as a parameter to the this property. You can start such a class as follows:
public class Line
{
public string this[MetroStation station]
{
}
}
When implementing the class, you should proceed the same way we have done so far following the rules of a method that takes an argument and returns a value other than void. Here is an example:
public class Line
{
public string Color { get; set; }
public string Between { get; set; }
public string And { get; set; }
private MetroStation[] stations = new MetroStation[10];
public string this[MetroStation station]
{
get
{
for(int i = 0; i < stations.Length - 1; i++)
{
if( station.StationNumber == stations[i].StationNumber)
{
return stations[i].ToString();
}
}
return "";
}
}
public Line()
{
stations = new MetroStation[12];
stations[0] = new MetroStation(2014, "Shady Grove", "Rockville", true, 32, "Red");
stations[1] = new MetroStation(1862, "Greenbelt", "Greenbelt", true, 60, "Green");
stations[2] = new MetroStation(9794, "Fort Totten", "DC", true, 10, "Yellow");
stations[3] = new MetroStation(1660, "Rockville", "Rockville", true, 69, "Red");
stations[4] = new MetroStation(9722, "White Flint", "Rockville", true, 32, "Red");
stations[5] = new MetroStation(1862, "Greenbelt", "Greenbelt", true, 60, "Green");
stations[6] = new MetroStation(1862, "Greenbelt", "Greenbelt", true, 60, "Yellow");
stations[7] = new MetroStation(3940, "College Park-U of MD", "College Park", true, 81, "Green");
stations[8] = new MetroStation(1417, "Forest Glen", "Silver Spring", true, 42, "Red");
stations[9] = new MetroStation(9737, "Wheaton", "Silver Spring", true, 36, "Red");
stations[10] = new MetroStation(8802, "Glenmont", "Silver Spring", true, 36, "Red");
stations[11] = new MetroStation(9273, "U Street/ African - Amer Civil War Memorial", "DC", false, 0, "Yellow");
}
}
After creating the property, you can use it. To do this, you must pass an object that is the type of the index. You can then use the returned value as you see fit. Here is an example:
<!DOCTYPE html>
<html>
<head>
<title>Metropolitan Transit System</title>
</head>
<body>
<h3>Metropolitan Transit System</h3>
@{
Line ln = new Line();
MetroStation ms = new MetroStation(9722, "White Flint", "Rockville", "Red");
ln.Between = "Rockville";
ln.And = "Silver Spring";
string station = ln[ms];
}
<p>Station: @station on the @ms.LineName line<br />
Transit from @ln.Between to @ln.And</p>
This would produce:
You can also directly pass an instance of the class in the square brackets of the object that holds the indexed property, as long as you specify the object. Here is an example:
<!DOCTYPE html>
<html>
<head>
<title>Metropolitan Transit System</title>
</head>
<body>
<h3>Metropolitan Transit System</h3>
@{
Line ln = new Line();
MetroStation ms = new MetroStation(9722, "White Flint", "Rockville", "Red");
ln.Between = "Rockville";
ln.And = "Silver Spring";
string station = ln[ms];
}
<p>Station: @station on the @ms.LineName line<br />
Transit from @ln.Between to @ln.And</p>
@{
ln = new Line();
ln.Between = "Greenbelt";
ln.And = "Franconia-Springfield";
station = ln[new MetroStation(1862, "Greenbelt", "Greenbelt", "Green")];
}
<p>Station: @station<br />
Transit from @ln.Between to @ln.And</p>
</body>
</html>
This would produce:
Overloading a Class-Based Indexed Property
As mentioned for indexers that return primitive types, you can overload an indexed property that produces an object or an indexed property that uses an object as index. You do this following the same rules applied to method overloading and arrays:
public class MetroStation
{
public bool Parking { get; set; }
public int BikeRacks { get; set; }
public string LineName { get; set; }
public string Location { get; set; }
public string StationName { get; set; }
public short StationNumber { get; set; }
public MetroStation(short id)
{
BikeRacks = id;
}
public MetroStation(short id, string station, string address, string lName)
{
StationNumber = id;
StationName = station;
Location = address;
LineName = lName;
}
public MetroStation(short id, string station, string address, bool parking, int bike, string lName)
{
StationNumber = id;
StationName = station;
Location = address;
Parking = parking;
BikeRacks = 0;
LineName = lName;
}
public override string ToString()
{
return $"{StationName} (#{StationNumber}, in {Location})";
}
}
public class Line
{
public string Color { get; set; }
public string Between { get; set; }
public string And { get; set; }
private MetroStation[] stations = new MetroStation[10];
public string this[short number]
{
get
{
for (int i = 0; i < stations.Length - 1; i++)
{
if (stations[i].StationNumber == number)
{
return stations[i].ToString();
}
}
return "";
}
}
public string this[MetroStation station]
{
get
{
for(int i = 0; i < stations.Length - 1; i++)
{
if( station.StationNumber == stations[i].StationNumber)
{
return stations[i].ToString();
}
}
return "";
}
}
public Line()
{
stations = new MetroStation[12];
stations[0] = new MetroStation(2014, "Shady Grove", "Rockville", true, 32, "Red");
stations[1] = new MetroStation(1862, "Greenbelt", "Greenbelt", true, 60, "Green");
stations[2] = new MetroStation(9794, "Fort Totten", "DC", true, 10, "Yellow");
stations[3] = new MetroStation(1660, "Rockville", "Rockville", true, 69, "Red");
stations[4] = new MetroStation(9722, "White Flint", "Rockville", true, 32, "Red");
stations[5] = new MetroStation(1862, "Greenbelt", "Greenbelt", true, 60, "Green");
stations[6] = new MetroStation(1862, "Greenbelt", "Greenbelt", true, 60, "Yellow");
stations[7] = new MetroStation(3940, "College Park-U of MD", "College Park", true, 81, "Green");
stations[8] = new MetroStation(1417, "Forest Glen", "Silver Spring", true, 42, "Red");
stations[9] = new MetroStation(9737, "Wheaton", "Silver Spring", true, 36, "Red");
stations[10] = new MetroStation(8802, "Glenmont", "Silver Spring", true, 36, "Red");
stations[11] = new MetroStation(9273, "U Street/ African - Amer Civil War Memorial", "DC", false, 0, "Yellow");
}
}
Remember that, to access an item, you must apply the right value to the square brackets of a variable of the class:
<!DOCTYPE html> <html> <head> <title>Metropolitan Transit System</title> </head> <body> <h3>Metropolitan Transit System</h3> @{ Line ln = new Line(); MetroStation ms = new MetroStation(9794, "Fort Totten", "DC", "Yellow"); ln.Between = "Greenbelt"; ln.And = "Huntington"; string station = ln[ms]; } <p>Station: @station on the @ms.LineName line<br /> Transit from @ln.Between to @ln.And</p> @{ ln = new Line(); ms = new MetroStation(3940); ln.Between = "Largo Town Center"; ln.And = "Franconia-Springfield"; station = ln[3940]; } <p>Station: @station<br /> Transit from @ln.Between to @ln.And</p> </body> </html>This would produce:
Read/Write Indexed Properties of Class Types
As done for a primitive type, you can allow the clients of your indexer to assign values to the array's elements. Once again, when defining the property, you should include a set accessor to it. In the set accessor, you should assign the value keyword to an element of the array. Here is an example:
public class SchoolRegistration { Student[] std = new Student[5]; public Student this[int i] { get { return std[i]; } set { std[i] = value; } } }
After doing this, you can create an element of the array by applying the square brackets to the instance of the class and assigning the desired value to it. The problem with the class is that, since it may have many fields (or properties), to completely define each element, you must provide a value to the member variables of the class itself. Here is an example:
public enum Classification { Female, Male, Unknown } public class Student { public long StudentID; public string firstName; public string lastName; public Classification Gender; public override string ToString() { string str = "Student ID: " + StudentID + " " + "First Name: " + firstName + " " + "Last Name: " + lastName + " " + "Gender: " + Gender; return str; } } public class SchoolRegistration { Student[] std = new Student[5]; public Student this[int i] { get { return std[i]; } set { std[i] = value; } } } public class Exercise { private void Create() { var registration = new SchoolRegistration(); var stud = new Student(); stud.StudentID = 604057; stud.firstName = "Gertrude"; stud.lastName = "Monayong"; stud.Gender = Classification.Female; registration[2] = stud; } }
Practical Learning: Ending the Lesson
|
||
Previous | Copyright © 2008-2019, FunctionX | Next |
|