Generics brings to C# concept of type parameters. Once designed, class (or method) can be reused with other data type substituted during instatiation
Generic types encapsulate operations that are not specific to a particular data type
class MyGenericCass <T1, T2>
{
public T1 someVar;
public T ReturnDefaultGenericValue1(){
return default(T1);
}
public T ReturnDefaultGenericValue2(){
return default(T2);
}
}
|
You cannot create instance from a generic type. First you need to create constructed type:
class SomeClass<T1, T2> {
T1 var1;
T2 var2;
}
|
class SomeClass<int, double> {
int var1;
double var2;
}
|
Constructed type is used as a regular type to construct instances and references:
var someVar = new SomeClass();
|
var someVar = new SomeClass<int, double>();
|
Constraints are listed as where clauses:
class SomeClass <T1, T2> where T1 : class, new()
where T2 : IEnumerable
{
…
}
|
Generic methods might be declared in both generic and nongeneric classes, and in structs and interfaces.
Generic methods have constraints section as well as class:
public T1 SomeMethod<T1, T2>(T2 input) where T1 : class T2 : new()
{
/* … */
}
|
Generic methods could be invoked with actual type parameters:
var val = SomeMethod<MyClass, MyClassWithCtor>;(new MyClassWithCtor());
|
Important note: if type can be determined by a compiler from passed parameter, declaration of type can be omitted
public void SomeMethod<T>(T someVal) {/* … */}
...
var val = SomeMethod<int>(myIntVal);
//the same as
var val = SomeMethod(myIntVal);
|
Generic structure:
public struct MyStruct<T> where T : class
{ /* … */ }
|
Generic interfaces:
public interface MyInterface<T> where T : class
{ /* … */ }
|
public class MyClass : MyInterface<MyClass1>, MyInterface<MyClass2>
{/* … interface implementation … */}
|
Generic delegates:
public delegate void MyDelegate<T>(T value); // Generic delegate
//…
var myDel = new MyDelegate<string>(PrintString); // Create inst of delegate
myDel += PrintUpperString; // Add a method
|
Collections are:
Collections are usually stored in following namespaces:
System.Collections
System.Collections.Generics
|
Most of collections are derived from following interfaces:
IEnumerable // basic interface that outlines enumerable object
ICollection // the most basic collection interface
IList // interface for simple list of items
ISet // defines sets. Allows to combine sets and introduces operations to manipulate sets.
IDictionary // for hash tables and dictionaries (key-value pair collections)
IComparer // introduces comparers an usually used by collections to sort elements.
|
Members of IEnumerable:
Members of IEnumerator:
var lst = new List<int>();
lst.Add(1); // { 1 }
lst.AddRange(new[] { 2, 3, 7, 6, 5, 4 }); // { 1, 2, 3, 7, 6, 5, 4 }
lst.Insert(index: 0, item: 0); // { 0, 1, 2, 3, 7, 6, 5, 4 }
lst.RemoveAt(index: 4); // { 0, 1, 2, 3, 6, 5, 4 }
lst.Remove(item: 1); // { 0, 2, 3, 6, 5, 4 }
lst.RemoveRange(index: 2, count: 3); // { 0, 2, 4 }
lst.Reverse(); // { 4, 2, 0 }
lst.Sort(); // { 0, 2, 4 }
bool hasTwo = lst.Contains(2); // true
int two = lst[1]; // 2
|
LinkedList
var lst = new LinkedList<string>(); // create linked list
var elem1 = lst.AddFirst(“isn’t”); //add first element
var elem2 = lst.AddBefore(elem1, “This”); //add element just before the first one
var elem3 = lst.AddAfter(elem1, “a”); //add element after element1
var elem4 = lst.AddLast(“list”); //add an element into the tail
var elem5 = lst.AddBefore(elem4, “singly”); //add an element before element 4
var elem6 = lst.AddAfter(elem5, “linked”); //add an element after element 5
lst.Last.Previous.Previous.Value = “doubly”; // use nav properties to navigate through values
lst.First.Next.Value = “is”;
foreach (var word in lst) print elements
Console.Write(word + “ “);
|
var dictionary = new Dictionary<int, string>(); // create dictionary
dictionary.Add(1, "one"); //add first element
dictionary[2] = "two"; // add second element
dictionary[2]= "updated_two"; // update second element
dictionary.Remove(2); // remove second element
if (!dictionary.ContainsKey(2)) // check if element with index 2 exists
dictionary.Add(2, "two"); // add second element
foreach(var a in dictionary)
Console.Write(a.Value);
|
Queue
var queue = new Queue<int>(); // init queue
queue.Enqueue(1); // add first element to queue
queue.Enqueue(2); // add second element to queue
var peekValue = queue.Peek(); // retrieve value from queue peek without deleting element (1)
var topItem = queue.Dequeue(); // get first element from top of the queue (1)
|
Stack
var stack = new Stack<int>(); // init stack
stack.Push(1); // add first element to stack
stack.Push(2); // add second element to stack
var peekValue = stack.Peek(); // get value from top of stack without deleting element (2)
var topItem = stack.Pop(); // get the most recently added element (2)
|
Set - is a collection of unique elements.
var ss1 = new SortedSet<char> {`A`,`B`,`C`,`D`}; //init first set
var ss2 = new SortedSet<char>{`E`,`D`,`F`} ; // init second set
ss1.Add(`Q`); // add new item to set 1
ss1.Remove(`A`); // remove an item from set 1
ss1.UnionWith(ss2); // union sets and store results to first set
ss1.ExceptWith(ss2); //remove set 2 from set 1
|
Both classes represent a collection of keys and values pair of data sorted by key.
var list = new List<int> {1, 2, 3, 4};
//equals to
var __temp = new List<int>();
__temp.Add(1);
__temp.Add(2);
__temp.Add(3);
__temp.Add(4);
var list = __temp;
|
The main condition for this feature - collection should support Add method
var ages = new Dictionary { { “Bart”, 26 }, { “John”, 62 } };
//equals to
var __temp = new Dictionary();
__temp.Add(“Bart”, 26);
__temp.Add(“John”, 62);
var ages = __temp;
|
int CompareTo<T>(T other)
|
int Compare(T x, T y)
|