Built-In Generic Class: List<> |
|
Fundamental Built-In Generic Classes |
Introduction to the Collections Namespaces |
The first public version of the .NET Framework was released as 1.1 in 2002. It contained a very impressive series of classes that could be used to create and manage collections. Most of the collection classes was created in the System.Collections namespace. The main goal was 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 flexibility of the new concept, as opposed to C++'s way of doing things, was the heavy use of interfaces. One of the classes introduced by the System.Collections namespaces is named ArrayList. |
The 2.0 release of the .NET Framework saw the arrival of generic classes. The idea was to modernize the capabilities of existing collection classes. As a result, a new namespace was created and named System.Collections.Generics. Of course, to use a class from this namespace, make sure you qualify the name of its class or add the namespace in your using section: using System.Collections.Generic; public class Exercise { public static int Main() { return 0; } } A new equivalent version was created for most of the classes and interfaces of the System.Collections namespaces.
One of the classes introduced by the System.Collections.Generics namespace is named List. This is probably the most commonly used generic class of the .NET Framework. It is primarily the System.Collections.Generics equivalent of the System.Collections's ArrayList. It allows you to create a list of any kind of value. Like any normal (non-static) class, to use a List object, you must first declare a variable for it. As a reminder of how to use a generic class, the formula to declare the variable is: List<TypeName> VariableName = new List<TypeName>(); You can also declare the variable using the var keyword: var VariableName = new List<TypeName>(); You can also use the dynamic keyword: dynamic VariableName = new List<TypeName>(); These techniques use the default constructor of the List class. If the list is made of values of primitive types, put that value in the TypeName placeholder. Here are examples of List variables: using System;
using System.Collections.Generic;
public class Exercise
{
public static int Main()
{
List<int> numbers = new List<int>();
var symbols = new List<char>();
dynamic names = new List<string>();
return 0;
}
}
If the list is made of objects, make sure you specify it. You can use one of the existing classes of the .NET Framework. Here are examples: using System; using System.Collections.Generic; public class Exercise { public static int Main() { List<EventArgs> eventArguments = new List<EventArgs>(); var enumerations = new List<Enum>(); dynamic exceptions = new List<Exception>(); return 0; } } Or you can create your own class. In both cases, the class must not be static.
The List class primarily supports all the necessary operations of a list. To allow you to add an item, the class is equipped with a method named Add. Its syntax is: public void Add(T item) To use it, simply pass the desired item to the method. If the value is a primitive type and if you want to pass a constant value, you must follow the rules of values of that type:
Here are examples: using System; using System.Collections.Generic; public class Exercise { public static int Main() { List<int> numbers = new List<int>(); numbers.Add(248); var symbols = new List<char>(); symbols.Add('%'); dynamic names = new List<string>(); names.Add("James"); return 0; } } Otherwise, you can first declare a variable for the value and pass the name of the variable to the List.Add() method. If you are using a class, you must follow the rules of classes:
You can use the List.Add() method to add an item or to add many items one at a time. As an alternative, to let you add many items at the same time, the List class provides the AddRange() method.
You can create a list in a method and return it. When defining the method, specify its return value as List<>. Inside the <> operator, write the type of value. Here is an example: using System;
using System.Collections.Generic;
public class Exercise
{
static List<int> GetNumbers()
{
}
}
You can then define the method however you like, before exiting, you must make sure you return a List<> object. To use the list produced by the method, you can assign its return to local variable. Here is an example: using System; using System.Collections.Generic; public class Exercise { static List<int> GetNumbers() { List<int> nbrs = new List<int>(); nbrs.Add(84); nbrs.Add(27407); nbrs.Add(5948); nbrs.Add(7); nbrs.Add(927482); return nbrs; } public static int Main() { List<int> numbers = new List<int>(); numbers = GetNumbers(); return 0; } }
You can use a list either in a local method where it is created or you can pass it to be processed by another method. You pass it the same way you would any value, using List<TypeOfValue> ArgumentName. Here is an example: using System;
using System.Collections.Generic;
public class Exercise
{
static void ShowNumbers(List<int> numbers)
{
}
}
In the method, you can use the argument any way you like.
To keep track of the number of items in a collection, the List class is equipped with a read-only property named Count: public int Count { get; } Here are examples of accessing it: public class Exercise { public static int Main() { List<Employee> contractors = new List<Employee>(); Employee empl = new Employee(397947, "David", "Redson", 18.75); contractors.Add(empl); empl = new Employee(840004, "Simao"); contractors.Add(empl); contractors.Add(new Employee()); var seasonals = new List<Employee>(); seasonals.Add(new Employee(848024, "Alima", "Bieyrou", 14.05)); seasonals.Add(new Employee(fName : "Robert", lName : "Nants")); dynamic identifications = new List<Employee>(); identifications.Add(new Employee(222222)); Console.WriteLine("This company has {0} contractors, {1} seasonal " + "employees, and {2} other type.", contractors.Count, seasonals.Count, identifications.Count); return 0; } } This would produce: This company has 3 contractors, 2 seasonal employees, and 1 other type. Press any key to continue . . .
When you declare a List variable, the compiler reserves a certain area and amount of memory for it. If you want, you can tell the compiler how much initial memory to reserve. To support this, the List class is equipped with a property named Capacity: public int Capacity { get; set; } To specify the initial capacity when declaring the List variable, you can use the following constructor: public List(int capacity); On the other hand, to get the capacity of a List variable, get the variable of its Capacity.
To let you access an item, the List class uses an indexed property named Item. This allows you to access its items using the [] operator. Here are examples: using System; using System.Collections.Generic; public class Exercise { public static int Main() { var name = new List<char>(); name.Add('A'); name.Add('p'); name.Add('l'); name.Add('e'); Console.Write("{0}", name[0]); Console.Write("{0}", name[1]); Console.Write("{0}", name[1]); Console.Write("{0}", name[2]); Console.Write("{0}", name[3]); Console.WriteLine(); return 0; } } This would produce: Apple Press any key to continue . . . You can also use a for loop to access each item of the list. Here is an example: using System; using System.Collections.Generic; public class Exercise { public static int Main() { var internetCode = new List<char>(); internetCode.Add('c'); internetCode.Add('o'); internetCode.Add('m'); Console.Write("http://www.kamerun."); for(int i = 0; i < internetCode.Count; i++) Console.Write("{0}", internetCode[i]); Console.WriteLine(); return 0; } } This would produce: http://www.kamerun.com Press any key to continue . . . If the list is made of objects of a class, to access an item, apply the square brackets to the variable, followed by a period, and followed by the desired member of the class. Here are examples: public class Exercise { public static int Main() { List<Employee> contractors = new List<Employee>(); Employee empl = new Employee(397947, "David", "Redson", 18.75); contractors.Add(empl); contractors.Add(new Employee(174966, "Alfred", "Swanson", 12.94)); empl = new Employee(840004, "Simao"); contractors.Add(empl); contractors.Add(new Employee(848024, "Alima", "Bieyrou", 14.05)); contractors.Add(new Employee(number: 397462, fName : "Robert", lName : "Nants")); dynamic identifications = new List<Employee>(); identifications.Add(new Employee(222222)); for (int i = 0; i < contractors.Count; i++) { Console.WriteLine("Employee #: {0}\nFirst Name: {1}\n" + "Last Name: {2}\n" + "Hourly Salary: {3:F}", contractors[i].EmployeeNumber, contractors[i].FirstName, contractors[i].LastName, contractors[i].HourlySalary); Console.WriteLine("-----------------------"); } return 0; } } This would produce: Employee #: 397947 First Name: David Last Name: Redson Hourly Salary: 18.75 ----------------------- Employee #: 174966 First Name: Alfred Last Name: Swanson Hourly Salary: 12.94 ----------------------- Employee #: 840004 First Name: Simao Last Name: Doe Hourly Salary: 12.00 ----------------------- Employee #: 848024 First Name: Alima Last Name: Bieyrou Hourly Salary: 14.05 ----------------------- Employee #: 397462 First Name: Robert Last Name: Nants Hourly Salary: 12.00 ----------------------- Press any key to continue . . .
In previous sections, we saw that you can use a for loop to scan a list of items. To support the foreach operator, the List class is equipped with a method named GetEnumerator. Its syntax is: public List<(Of <(<'T>)>)>..::..Enumerator GetEnumerator(); Normally, you don't need to know anything about this method. You use foreach the same was we saw for arrays. Here is an example: public class Exercise { public static int Main() { List<Employee> employees = new List<Employee>(); Employee empl = new Employee(397947, "David", "Redson", 18.75); employees.Add(empl); employees.Add(new Employee(174966, "Alfred", "Swanson", 12.94)); employees.Add(new Employee(848024, "Alima", "Bieyrou", 14.05)); employees.Add(new Employee(number: 397462, fName: "Robert", lName: "Nants", salary: 22.15)); foreach (Employee staffMember in employees) { Console.WriteLine("================================"); Console.WriteLine("Employee Record"); Console.WriteLine("--------------------------------"); Console.WriteLine("Employee #: {0}", staffMember.EmployeeNumber); Console.WriteLine("First Name: {0}", staffMember.FirstName); Console.WriteLine("Last Name: {0}", staffMember.LastName); Console.WriteLine("Hourly Salary: {0}", staffMember.HourlySalary); } return 0; } }
The List class provides its own method that performs the operation of foreach. Its name is ForEach and its syntax is: public void ForEach(Action<T> action); This method expects a function that defines what to do every time the compiler visits a members of the list. You do this by creating a method to do something on each member of the List<> collection and then pass that method to ForEach(). Here is an example: public class Exercise { public void ShowEmployee(Employee empl) { Console.WriteLine("================================"); Console.WriteLine("Employee Record"); Console.WriteLine("--------------------------------"); Console.WriteLine("Employee #: {0}", empl.EmployeeNumber); Console.WriteLine("First Name: {0}", empl.FirstName); Console.WriteLine("Last Name: {0}", empl.LastName); Console.WriteLine("Hourly Salary: {0}", empl.HourlySalary); } public static int Main() { Exercise exo = new Exercise(); List<Employee> employees = new List<Employee>(); Employee empl = new Employee(397947, "David", "Redson", 18.75); employees.Add(empl); employees.Add(new Employee(174966, "Alfred", "Swanson", 12.94)); employees.Add(new Employee(848024, "Alima", "Bieyrou", 14.05)); employees.Add(new Employee(number: 397462, fName: "Robert", lName: "Nants", salary: 22.15)); employees.ForEach(exo.ShowEmployee); return 0; } }
The List class provides various means of finding out whether an item exists in a list. One of the methods you can use is named Contains. Its syntax is: public bool Contains(T item); This methods takes as argument the item to look for. If that item exists in the list, the method returns true. Otherwise, it returns false. This method is easy to use on a list that contains value of primitive types. Here is an example: using System; using System.Collections.Generic; public class Exercise { public static int Main() { var connection = new List<char>(); connection.Add('c'); connection.Add('o'); connection.Add('n'); connection.Add('n'); connection.Add('e'); connection.Add('c'); connection.Add('t'); connection.Add('i'); connection.Add('o'); connection.Add('n'); for (int i = 0; i < connection.Count; i++) Console.Write("{0}", connection[i]); Console.WriteLine(); if (connection.Contains('e')) Console.WriteLine("The list contains 'e'"); else Console.WriteLine("There is no 'e' in the list"); if (connection.Contains('g')) Console.WriteLine("The list contains 'g'"); else Console.WriteLine("There is no 'g' in the list"); return 0; } } This would produce: connection The list contains 'e' There is no 'g' in the list Press any key to continue . . . This works because each structure of a primitive type is equipped to compare two of its values. The comparison would not work directly if the list is made of values of your own class. Consider the following: using System;
using System.Collections.Generic;
public class Employee
{
public long EmployeeNumber { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public double HourlySalary { get; set; }
public Employee(long number = 0, string fName = "John",
string lName = "Doe", double salary = 12.05D)
{
EmployeeNumber = number;
FirstName = fName;
LastName = lName;
HourlySalary = salary;
}
public override string ToString()
{
base.ToString();
return string.Format("================================\n" +
"Employee Record\n" +
"--------------------------------\n" +
"Employee #: {0}\nFirst Name: {1}\n" +
"Last Name: {2}\nHourly Salary: {3}",
EmployeeNumber, FirstName,
LastName, HourlySalary);
}
}
public class Exercise
{
public static int Main()
{
List<Employee> employees = new List<Employee>();
Employee empl = new Employee(397947, "David", "Redson", 18.75);
employees.Add(empl);
employees.Add(new Employee(174966, "Alfred", "Swanson", 12.94));
employees.Add(new Employee(848024, "Alima", "Bieyrou", 14.05));
employees.Add(new Employee(number: 397462, fName: "Robert",
lName: "Nants", salary: 22.15));
Employee member = new Employee(174966, "Alfred", "Swanson", 12.94);
bool exists = employees.Contains(member);
if (exists == true)
Console.WriteLine("The list contains the employee");
else
Console.WriteLine("No record of that employee was found");
return 0;
}
}
This would produce: No record of that employee was found Press any key to continue . . . Notice that the compiler was not able to find the item even though it actually exists in the list. To make this method work on your class, you must override the Equals() method. Here is an example: using System;
using System.Collections.Generic;
public class Employee
{
public long EmployeeNumber { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public double HourlySalary { get; set; }
public Employee(long number = 0, string fName = "John",
string lName = "Doe", double salary = 12.05D)
{
EmployeeNumber = number;
FirstName = fName;
LastName = lName;
HourlySalary = salary;
}
public override bool Equals(object obj)
{
Employee e = (Employee)obj;
if ((e.EmployeeNumber == this.EmployeeNumber) &&
(e.FirstName == this.FirstName) &&
(e.LastName == this.LastName) &&
(e.HourlySalary == this.HourlySalary))
return true;
else
return false;
}
public override string ToString()
{
base.ToString();
return string.Format("================================\n" +
"Employee Record\n" +
"--------------------------------\n" +
"Employee #: {0}\nFirst Name: {1}\n" +
"Last Name: {2}\nHourly Salary: {3}",
EmployeeNumber, FirstName,
LastName, HourlySalary);
}
}
public class Exercise
{
public static int Main()
{
. . . No Change
return 0;
}
}
This time, the program would produce: The list contains the employee Press any key to continue . . .
You can ask the compiler to look for an item in the list and, if it finds it, to give you the index of that item. To make this request, use the IndexOf() method. It is overloaded with three versions. One of them uses the following syntax: public int IndexOf(T item); When calling this method, if the list is made of values of primitive types, pass the value as argument. Here is an example: using System; using System.Collections.Generic; public class Exercise { public static int Main() { var connection = new List<char>(); connection.Add('c'); connection.Add('o'); connection.Add('n'); connection.Add('n'); connection.Add('e'); connection.Add('c'); connection.Add('t'); connection.Add('i'); connection.Add('o'); connection.Add('n'); for (int i = 0; i < connection.Count; i++) Console.Write("{0}", connection[i]); Console.WriteLine(); Console.WriteLine("The index of 'n' is {0}", connection.IndexOf('n')); return 0; } } This would produce: connection The index of 'n' is 2 Press any key to continue . . . As mentioned for the Contains() method, when you call the IndexOf() method, the compiler compares each member of the collection with the value passed as argument. This works fine on value of primitive types because they have built-in comparison in their structures. If you want this to work on a class you created, you must override the Equals() method. If you call the above version of the IndexOf() method, the compiler would look for the item in the entire list starting from the beginning, the 0-index. If you want, you can ask the compiler to start looking at a specific position. To do this, use the following version of the IndexOf() method: public int IndexOf(T item, int index); This time, besides the item, pass an index as the second argument. The compiler would look for the item starting at that index to the end. When you use the IndexOf() method, the compiler would look for the item starting from the left to the right. If you prefer to look for the item from the end of the list, you can use the LastIndexOf() method. It is overloaded with three versions. One of them uses a syntax as: public int LastIndexOf(T item); Here is an example of calling this method: using System; using System.Collections.Generic; public class Exercise { public static int Main() { var connection = new List<char>(); connection.Add('c'); connection.Add('o'); connection.Add('n'); connection.Add('n'); connection.Add('e'); connection.Add('c'); connection.Add('t'); connection.Add('i'); connection.Add('o'); connection.Add('n'); for (int i = 0; i < connection.Count; i++) Console.Write("{0}", connection[i]); Console.WriteLine(); Console.WriteLine("The index of 'n' from the end to the beginning is {0}", connection.LastIndexOf('n')); return 0; } } This would produce: connection The index of 'n' from the end to the beginning is 9 Press any key to continue . . . If you prefer to look for the item starting at a certain index from the end, use the following syntax: public int LastIndexOf(T item, int index);
There are various ways you can remove an item from a list. To let you delete an item based on its index, you can call the RemoveAt() method. Its syntax is: public void RemoveAt(int index); When calling this method, pass the index of the undesired item. Here is an example: using System;
using System.Collections.Generic;
public class Exercise
{
public static int Main()
{
var internetCode = new List<char>();
internetCode.Add('c');
internetCode.Add('o');
internetCode.Add('m');
Console.Write("http://www.kamerun.");
for(int i = 0; i < internetCode.Count; i++)
Console.Write("{0}", internetCode[i]);
Console.WriteLine();
internetCode.RemoveAt(1);
Console.Write("http://www.kamerun.");
for (int i = 0; i < internetCode.Count; i++)
Console.Write("{0}", internetCode[i]);
Console.WriteLine();
return 0;
}
}
This would produce: http://www.kamerun.com http://www.kamerun.cm Press any key to continue . . . As you can see, the RemoveAt() method is the easy way to delete an item from a list if you know its index. Another way you can proceed would consist of finding out first if the item exists in the list, get its index, and then pass that index.
Still using an index, but instead of deleting just one, you can remove a range of value from a list. To support this, the List<> class provides the RemoveRange() method. Its syntax is: public void RemoveRange(int index, int count); The first item is the index from where to start deleting items. The second argument specifies the number of items to delete from the index to the end of the list.
Instead of locating an item based on its index, you can ask the List class to look for it. To support this, it is equipped with a method named Remove. Its syntax is: public bool Remove(T item); In this case, you pass a definition of the item to the method. Here is an example: using System;
using System.Collections.Generic;
public class Exercise
{
public static int Main()
{
var internetCode = new List<char>();
internetCode.Add('c');
internetCode.Add('o');
internetCode.Add('m');
Console.Write("http://www.kamerun.");
for(int i = 0; i < internetCode.Count; i++)
Console.Write("{0}", internetCode[i]);
Console.WriteLine();
internetCode.Remove('o');
Console.Write("http://www.kamerun.");
for (int i = 0; i < internetCode.Count; i++)
Console.Write("{0}", internetCode[i]);
Console.WriteLine();
return 0;
}
}
When you call the List.Remove() method, the compiler would look for the item in the collection:
Notice that the list contains three Ns but only the first was removed. If the item is based on a class, you must (it is your responsibility, the List class it not equipped to) provide a way to identify an item. This is usually done by overriding the Equals() method.
To delete all items from a list, call the Clear() method. Its syntax is: public void Clear();
If you have an existing list, you can use a range of indices from it to retrieve a new list. To support this operation, the List class provides the GetRange() method whose syntax is: public List<T> GetRange(int index, int count); The first argument of this method is the start point of the range. The second argument is the number of items from the index to include in the new list. Here are examples of calling this method: using System; using System.Collections.Generic; public class Exercise { public static int Main() { var connection = new List<char>(); connection.Add('c'); connection.Add('o'); connection.Add('n'); connection.Add('n'); connection.Add('e'); connection.Add('c'); connection.Add('t'); connection.Add('i'); connection.Add('o'); connection.Add('n'); for (int i = 0; i < connection.Count; i++) Console.Write("{0}", connection[i]); Console.WriteLine(); List<char> connect = connection.GetRange(0, 7); for (int i = 0; i < connect.Count; i++) Console.Write("{0}", connect[i]); Console.WriteLine(); List<string> person = new List<string>(); person.Add("Paul"); person.Add("Martin"); person.Add("Souffrance"); person.Add("Eto"); person.Add("Zambo"); for (int i = 0; i < person.Count; i++) Console.Write("{0} ", person[i]); Console.WriteLine(); List<string> pers = person.GetRange(1, 2); for (int i = 0; i < pers.Count; i++) Console.Write("{0} ", pers[i]); Console.WriteLine(); return 0; } } This would produce: connection connect Paul Martin Souffrance Eto Zambo Martin Souffrance Press any key to continue . . . In the same way, you can create a sub-list of objects from an existing collection.
To convert a list into an array, you can call the ToArray() method of the List<> class. Its syntax is: public T[] ToArray(); Here is an example of calling this method: public class Exercise { public static int Main() { List<Employee> contractors = new List<Employee>(); Employee empl = new Employee(397947, "David", "Redson", 18.75); contractors.Add(empl); contractors.Add(new Employee(174966, "Alfred", "Swanson", 12.94)); contractors.Add(new Employee(405809, "Amie", "Tripp", 16.55)); contractors.Add(new Employee(294815, "Theodore", "Ludlum", 8.05)); contractors.Add(new Employee(848024, "Alima", "Bieyrou", 14.05)); contractors.Add(new Employee(number: 397462, fName: "Robert", lName: "Nants", salary : 22.15)); Employee[] employees = contractors.ToArray(); foreach (Employee staff in employees) Console.WriteLine(staff); return 0; } } |
|||||||||||||||||||||||||||||||||||||||||||||
|
||
Home | Copyright © 2010-2016, FunctionX | |
|