DocumentManager
namespace Wrox.ProCSharp.Generics { public interface IDocument { string Title { get; set; } string Content { get; set; } } public class Document : IDocument { public Document() { } public Document(string title, string content) { this.Title = title; this.Content = content; } public string Title { get; set; } public string Content { get; set; } } }
using System; using System.Collections.Generic; namespace Wrox.ProCSharp.Generics { public class DocumentManager<TDocument> where TDocument : IDocument { private readonly Queue<TDocument> documentQueue = new Queue<TDocument>(); public void AddDocument(TDocument doc) { lock (this) { documentQueue.Enqueue(doc); } } public bool IsDocumentAvailable { get { return documentQueue.Count > 0; } } public void DisplayAllDocuments() { foreach (TDocument doc in documentQueue) { Console.WriteLine(doc.Title); } } public TDocument GetDocument() { TDocument doc = default(TDocument); lock (this) { doc = documentQueue.Dequeue(); } return doc; } } }
using System; namespace Wrox.ProCSharp.Generics { class Program { static void Main() { var dm = new DocumentManager<Document>(); dm.AddDocument(new Document("Title A", "Sample A")); dm.AddDocument(new Document("Title B", "Sample B")); dm.DisplayAllDocuments(); if (dm.IsDocumentAvailable) { Document d = dm.GetDocument(); Console.WriteLine(d.Content); } } } }
GenericMethods
using System; namespace Wrox.ProCSharp.Generics { public interface IAccount { decimal Balance { get; } string Name { get; } } public class Account : IAccount { public string Name { get; private set; } public decimal Balance { get; private set; } public Account(string name, Decimal balance) { this.Name = name; this.Balance = balance; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Wrox.ProCSharp.Generics { public static class Algorithm { public static decimal AccumulateSimple(IEnumerable<Account> source) { decimal sum = 0; foreach (Account a in source) { sum += a.Balance; } return sum; } public static decimal Accumulate<TAccount>(IEnumerable<TAccount> source) where TAccount : IAccount { decimal sum = 0; foreach (TAccount a in source) { sum += a.Balance; } return sum; } public static T2 Accumulate<T1, T2>(IEnumerable<T1> source, Func<T1, T2, T2> action) { T2 sum = default(T2); foreach (T1 item in source) { sum = action(item, sum); } return sum; } } }
using System.Collections.Generic; namespace Wrox.ProCSharp.Generics { class Program { static void Main() { var accounts = new List<Account>() { new Account("Christian", 1500), new Account("Stephanie", 2200), new Account("Angela", 1800), new Account("Matthias", 2400) }; decimal amount = Algorithm.AccumulateSimple(accounts); amount = Algorithm.Accumulate(accounts); amount = Algorithm.Accumulate<Account, decimal>(accounts, (item, sum) => sum += item.Balance); } } }
LinkedListObjects
using System.Collections; namespace Wrox.ProCSharp.Generics { public class LinkedList : IEnumerable { public LinkedListNode First { get; private set; } public LinkedListNode Last { get; private set; } public LinkedListNode AddLast(object node) { var newNode = new LinkedListNode(node); if (First == null) { First = newNode; Last = First; } else { Last.Next = newNode; Last = newNode; } return newNode; } public IEnumerator GetEnumerator() { LinkedListNode current = First; while (current != null) { yield return current.Value; current = current.Next; } } } }
namespace Wrox.ProCSharp.Generics { public class LinkedListNode { public LinkedListNode(object value) { this.Value = value; } public object Value { get; private set; } public LinkedListNode Next { get; internal set; } public LinkedListNode Prev { get; internal set; } } }
using System; namespace Wrox.ProCSharp.Generics { class Program { static void Main() { var list1 = new LinkedList(); list1.AddLast(2); list1.AddLast(4); list1.AddLast("6"); foreach (int i in list1) { Console.WriteLine(i); } } } }
LinkedListSample
using System.Collections; using System.Collections.Generic; namespace Wrox.ProCSharp.Generics { public class LinkedList<T> : IEnumerable<T> { public LinkedListNode<T> First { get; private set; } public LinkedListNode<T> Last { get; private set; } public LinkedListNode<T> AddLast(T node) { var newNode = new LinkedListNode<T>(node); if (First == null) { First = newNode; Last = First; } else { Last.Next = newNode; Last = newNode; } return newNode; } public IEnumerator<T> GetEnumerator() { LinkedListNode<T> current = First; while (current != null) { yield return current.Value; current = current.Next; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }
namespace Wrox.ProCSharp.Generics { public class LinkedListNode<T> { public LinkedListNode(T value) { this.Value = value; } public T Value { get; private set; } public LinkedListNode<T> Next { get; internal set; } public LinkedListNode<T> Prev { get; internal set; } } }
using System; namespace Wrox.ProCSharp.Generics { class Program { static void Main() { var list2 = new LinkedList<int>(); list2.AddLast(1); list2.AddLast(3); list2.AddLast(5); foreach (int i in list2) { Console.WriteLine(i); } var list3 = new LinkedList<string>(); list3.AddLast("2"); list3.AddLast("four"); list3.AddLast("foo"); foreach (string s in list3) { Console.WriteLine(s); } } } }
Specialization
using System; namespace Wrox.ProCSharp.Generics { public class MethodOverloads { public void Foo<T>(T obj) { Console.WriteLine("Foo<T>(T obj), obj type: {0}", obj.GetType().Name); } public void Foo(int x) { Console.WriteLine("Foo(int x)"); } public void Bar<T>(T obj) { Foo(obj); } } class Program { static void Main() { var test = new MethodOverloads(); test.Foo(33); test.Foo("abc"); test.Bar(44); } } }
Variance
using System; namespace Wrox.ProCSharp.Generics { public class ShapeDisplay : IDisplay<Shape> { public void Show(Shape s) { Console.WriteLine("{0} Width: {1}, Height: {2}", s.GetType().Name, s.Width, s.Height); } } }
using System; namespace Wrox.ProCSharp.Generics { public class Shape { public double Width { get; set; } public double Height { get; set; } public override string ToString() { return String.Format("Width: {0}, Height: {1}", Width, Height); } } }
using System; namespace Wrox.ProCSharp.Generics { public class RectangleCollection : IIndex<Rectangle> { private Rectangle[] data = new Rectangle[3] { new Rectangle { Height=2, Width=5 }, new Rectangle { Height=3, Width=7}, new Rectangle { Height=4.5, Width=2.9} }; private static RectangleCollection coll; public static RectangleCollection GetRectangles() { return coll ?? (coll = new RectangleCollection()); } public Rectangle this[int index] { get { if (index < 0 || index > data.Length) throw new ArgumentOutOfRangeException("index"); return data[index]; } } public int Count { get { return data.Length; } } } }
namespace Wrox.ProCSharp.Generics { public class Rectangle : Shape { } }
using System; namespace Wrox.ProCSharp.Generics { class Program { static void Main() { IIndex<Rectangle> rectangles = RectangleCollection.GetRectangles(); IIndex<Shape> shapes = rectangles; for (int i = 0; i < shapes.Count; i++) { Console.WriteLine(shapes[i]); } IDisplay<Shape> shapeDisplay = new ShapeDisplay(); IDisplay<Rectangle> rectangleDisplay = shapeDisplay; rectangleDisplay.Show(rectangles[0]); } } }
namespace Wrox.ProCSharp.Generics { // covariant public interface IIndex<out T> { T this[int index] { get; } int Count { get; } } }
namespace Wrox.ProCSharp.Generics { // contra-variant public interface IDisplay<in T> { void Show(T item); } }