
14. Generic, NonGeneric
Generic vs. Non-Generic Collections
In C#, collections can be broadly categorized into non-generic (older style) and generic collections.
Generic Collections
- Example:
List<int>
,Dictionary<string, DateTime>
,Queue<double>
, etc.
- Type-Safe: The compiler knows the exact type stored in the collection, allowing better performance and no need for boxing or unboxing of value types.
- Advantages:
- Avoids runtime errors due to invalid casts.
- Better performance due to less boxing/unboxing.
- Improved readability since the type is explicit in
List<T>
,Queue<T>
, etc.
List<int> numbers = new List<int>();
numbers.Add(1); // No boxing needed
Non-Generic Collections
- Examples:
ArrayList
,Hashtable
,SortedList
(from older versions of .NET).
- Store objects of any type via
object
.
- Disadvantages:
- Boxing and unboxing happen for value types, which is less efficient.
- Potential runtime errors if you accidentally cast to the wrong type.
ArrayList arrayList = new ArrayList();
int value = 100;
arrayList.Add(value); // Boxing occurs
int unboxedValue = (int)arrayList[0]; // Unboxing occurs
Boxing and Unboxing
Boxing
- Converts a value type (e.g.,
int
,bool
) to a reference type (object
).
- Internally, a copy of the value is created on the heap.
int a = 100;
object obj = a; // Boxing: 'a' is copied onto the heap as an object
Unboxing
- Converts a reference type (
object
) back to a value type.
- Requires explicit casting.
int data = (int)obj; // Unboxing: 'obj' is cast back to int
Boxing/unboxing can negatively impact performance due to copying and potential invalid casts.
Collections Overview
Stack
- LIFO (Last In First Out) structure.
Push()
to add,Pop()
to remove the top item.
Queue
- FIFO (First In First Out) structure.
Enqueue()
to add,Dequeue()
to remove from the front.
Hashtable
- Non-generic key/value collection using
object
as both key and value type.
- Hash-based, so retrieval is generally O(1) time, but requires boxing for value types.
SortedList
- Non-generic sorted key/value collection.
- Maintains keys in ascending order.
- Also requires boxing for value types.
Extension Methods
An extension method adds new methods to an existing type without modifying its source code. In C#, you define a static method in a static class, and the first parameter has the this
keyword to indicate which type to extend.
public static class StringExtensions
{
public static int WordCount(this string input)
{
return input.Split(new[] { ' ', '.', '!' },
StringSplitOptions.RemoveEmptyEntries).Length;
}
}
// Usage:
string sentence = "Hello world from extension methods!";
int count = sentence.WordCount();
Console.WriteLine(count); // Outputs the number of words
Generic Constraints
When defining a generic class or method, you can specify constraints on T
:
public class MyGenericClass<T> where T : class
{
// T must be a reference type
}
public class AnotherGenericClass<T> where T : struct
{
// T must be a value type (including enums, user-defined structs)
}
public class InterfaceBound<T> where T : IDisposable
{
// T must implement IDisposable
}
These constraints ensure that the type parameter T
fulfills the required characteristics, whether it’s a reference type, a value type, or something that implements a specific interface.
Reference
The content in this document is based on the original notes provided in Azerbaijani. For further details, you can refer to the original document using the following link:
Original Note - Azerbaijani Version