第十章 集合

BitArraySample

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Text;

namespace BitArraySample
{
  class Program
  {
    static void BitArrayDemo()
    {
      var bits1 = new BitArray(8);
      bits1.SetAll(true);
      bits1.Set(1, false);
      bits1[5] = false;
      bits1[7] = false;
      Console.Write("initialized: ");
      DisplayBits(bits1);
      Console.WriteLine();


      DisplayBits(bits1);
      bits1.Not();
      Console.Write(" not ");
      DisplayBits(bits1);
      Console.WriteLine();

      var bits2 = new BitArray(bits1);
      bits2[0] = true;
      bits2[1] = false;
      bits2[4] = true;
      DisplayBits(bits1);
      Console.Write(" or ");
      DisplayBits(bits2);
      Console.Write(" : ");
      bits1.Or(bits2);
      DisplayBits(bits1);
      Console.WriteLine();


      DisplayBits(bits2);
      Console.Write(" and ");
      DisplayBits(bits1);
      Console.Write(" : ");
      bits2.And(bits1);
      DisplayBits(bits2);
      Console.WriteLine();

      DisplayBits(bits1);
      Console.Write(" xor ");
      DisplayBits(bits2);
      bits1.Xor(bits2);
      Console.Write(" : ");
      DisplayBits(bits1);
      Console.WriteLine();
    }

    static void BitVectorDemo()
    {

      var bits1 = new BitVector32();
      int bit1 = BitVector32.CreateMask();
      int bit2 = BitVector32.CreateMask(bit1);
      int bit3 = BitVector32.CreateMask(bit2);
      int bit4 = BitVector32.CreateMask(bit3);
      int bit5 = BitVector32.CreateMask(bit4);

      bits1[bit1] = true;
      bits1[bit2] = false;
      bits1[bit3] = true;
      bits1[bit4] = true;
      Console.WriteLine(bits1);

      bits1[0xabcdef] = true;
      Console.WriteLine(bits1);


      int received = 0x79abcdef;

      var bits2 = new BitVector32(received);
      Console.WriteLine(bits2);
      // sections: FF EEE DDD CCCC BBBBBBBB AAAAAAAAAAAA
      BitVector32.Section sectionA = BitVector32.CreateSection(0xfff);
      BitVector32.Section sectionB = BitVector32.CreateSection(0xff, sectionA);
      BitVector32.Section sectionC = BitVector32.CreateSection(0xf, sectionB);
      BitVector32.Section sectionD = BitVector32.CreateSection(0x7, sectionC);
      BitVector32.Section sectionE = BitVector32.CreateSection(0x7, sectionD);
      BitVector32.Section sectionF = BitVector32.CreateSection(0x3, sectionE);



      Console.WriteLine("Section A: " + IntToBinaryString(bits2[sectionA], true));
      Console.WriteLine("Section B: " + IntToBinaryString(bits2[sectionB], true));
      Console.WriteLine("Section C: " + IntToBinaryString(bits2[sectionC], true));
      Console.WriteLine("Section D: " + IntToBinaryString(bits2[sectionD], true));
      Console.WriteLine("Section E: " + IntToBinaryString(bits2[sectionE], true));
      Console.WriteLine("Section F: " + IntToBinaryString(bits2[sectionF], true));


    }

    static string IntToBinaryString(int bits, bool removeTrailingZero)
    {
      var sb = new StringBuilder(32);

      for (int i = 0; i < 32; i++)
      {
        if ((bits & 0x80000000) != 0)
        {
          sb.Append("1");
        }
        else
        {
          sb.Append("0");
        }
        bits = bits << 1;
      }
      string s = sb.ToString();
      if (removeTrailingZero)
        return s.TrimStart('0');
      else
        return s;
    }

    static void Main()
    {
      // BitArrayDemo();
      BitVectorDemo();
    }


    static void DisplayBits(BitArray bits)
    {
      foreach (bool bit in bits)
      {
        Console.Write(bit ? 1 : 0);
      }
    }
  }
}
View Code

ConcurrentSample

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Wrox.ProCSharp.Collections
{
  public class Info
  {
    public string Word { get; set; }
    public int Count { get; set; }
    public string Color { get; set; }

    public override string ToString()
    {
      return String.Format("{0} x: {1}", Count, Word);
    }
  }
}
View Code
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Wrox.ProCSharp.Collections
{
  class Program
  {
    static void Main()
    {
      // BlockingDemo();

      //BlockingDemoSimple();

      PipelineSample();

      Console.ReadLine();

    }

    private static void ReadFileNames(string path, BlockingCollection<string> output)
    {
      foreach (string filename in Directory.EnumerateFiles(path, "*.cs"))
      {
        output.Add(filename);
      }
      output.CompleteAdding();
    }

    private static void AddOrIncrementValue(string key, ConcurrentDictionary<string, int> dict)
    {
      bool success = false;
      while (!success)
      {
        int value;
        if (dict.TryGetValue(key, out value))
        {
          if (dict.TryUpdate(key, value + 1, value))
          {
            success = true;
          }
        }
        else
        {
          if (dict.TryAdd(key, 1))
          {
            success = true;
          }
        }
      }
    }

    

    private static async void LoadContent(BlockingCollection<string> input, ConcurrentDictionary<string, int> output)
    {
      foreach (var filename in input.GetConsumingEnumerable())
      {
        using (FileStream stream = File.OpenRead(filename))
        {
          var reader = new StreamReader(stream);
          string line = await reader.ReadLineAsync();
          string[] words = line.Split(' ', ';', '	');
          foreach (var word in words)
          {
            AddOrIncrementValue(word, output);
          }
        }
      }
    }

    private static void TransferContent(ConcurrentDictionary<string, int> input, BlockingCollection<Info> output)
    {
      foreach (var word in input.Keys)
        {
        int value;
        if (input.TryGetValue(word, out value))
        {
              output.Add(new Info { Word = word, Count = value });
        }
        }
    }
    private static void ShowContent(BlockingCollection<Info> input)
    {
      foreach (var item in input.GetConsumingEnumerable())
      {
        Console.WriteLine(item);
      }
    }

    private static async void PipelineSample()
    {
      BlockingCollection<string> coll1 = new BlockingCollection<string>();
      ConcurrentDictionary<string, int> coll2 = new ConcurrentDictionary<string,int>();
      BlockingCollection<Info> coll3 = new BlockingCollection<Info>();
      Task t1 = Task.Factory.StartNew(() => ReadFileNames(@"C:	empMvcApplication1MvcApplication1Controllers", coll1), TaskCreationOptions.LongRunning);
      Console.WriteLine("started stage 1");
      Task t2 = Task.Factory.StartNew(() => LoadContent(coll1, coll2), TaskCreationOptions.LongRunning);
      Console.WriteLine("started stage 2");
      await Task.WhenAll(t1, t2);
      Console.WriteLine("stage 1 and 2 completed");
      Task t3 = Task.Factory.StartNew(() => TransferContent(coll2, coll3), TaskCreationOptions.LongRunning);
      Task t4 = Task.Factory.StartNew(() => ShowContent(coll3), TaskCreationOptions.LongRunning);
      Console.WriteLine("stages 3 and 4 started");
      await Task.WhenAll(t3, t4);
      Console.WriteLine("all finished");


    }

    static void BlockingDemoSimple()
    {
      var sharedCollection = new BlockingCollection<int>();
      var events = new ManualResetEventSlim[2];
      var waits = new WaitHandle[2];
      for (int i = 0; i < 2; i++)
      {
        events[i] = new ManualResetEventSlim(false);
        waits[i] = events[i].WaitHandle;
      }

      var producer = new Thread(obj =>
      {
        var state = (Tuple<BlockingCollection<int>, ManualResetEventSlim>)obj;
        var coll = state.Item1;
        var ev = state.Item2;
        var r = new Random();

        for (int i = 0; i < 300; i++)
        {
          coll.Add(r.Next(3000));
        }
        ev.Set();
      });
      producer.Start(Tuple.Create<BlockingCollection<int>, ManualResetEventSlim>(sharedCollection, events[0]));

      var consumer = new Thread(obj =>
      {
        var state = (Tuple<BlockingCollection<int>, ManualResetEventSlim>)obj;
        var coll = state.Item1;
        var ev = state.Item2;

        for (int i = 0; i < 300; i++)
        {
          int result = coll.Take();
        }
        ev.Set();
      });
      consumer.Start(Tuple.Create<BlockingCollection<int>, ManualResetEventSlim>(sharedCollection, events[1]));

      if (!WaitHandle.WaitAll(waits))
        Console.WriteLine("wait failed");
      else
        Console.WriteLine("reading/writing finished");

    }

    static async void BlockingDemo()
    {
      const int taskCount = 10;
      ManualResetEventSlim[] events = new ManualResetEventSlim[taskCount];
      WaitHandle[] waits = new WaitHandle[taskCount];
      var consoleLock = new object();

      for (int task = 0; task < taskCount; task++)
      {
        events[task] = new ManualResetEventSlim(false);
        waits[task] = events[task].WaitHandle;
      }

      var sharedCollection = new BlockingCollection<int>();


      for (int task = 0; task < taskCount >> 1; task++)
      {

        var producer = new Task((state) =>
        {
          var coll = ((Tuple<BlockingCollection<int>, ManualResetEventSlim>)state).Item1;
          var wait = ((Tuple<BlockingCollection<int>, ManualResetEventSlim>)state).Item2;
          var r = new Random();
          for (int i = 0; i < 300; i++)
          {
            int data = r.Next(30000);
            if (!coll.TryAdd(data))
            {
              Console.WriteLine("**** couldn't add");
            }
            else
            {
              lock (consoleLock)
              {
                Console.ForegroundColor = ConsoleColor.Cyan;
                Console.Write(" {0} ", data);
                Console.ResetColor();
              }
            }
            Thread.Sleep(r.Next(40));
          }
          wait.Set();
        }, Tuple.Create<BlockingCollection<int>, ManualResetEventSlim>(sharedCollection, events[task]));

        producer.Start();
//        producer.Start(Tuple.Create<BlockingCollection<int>, ManualResetEventSlim>(sharedCollection, events[task]));
      }

      await Task.Delay(500); // give the producers a headstart
  

      for (int task = taskCount >> 1; task < taskCount; task++)
      {
        var consumer = new Task((state) =>
        {
          var coll = ((Tuple<BlockingCollection<int>, ManualResetEventSlim>)state).Item1;
          var wait = ((Tuple<BlockingCollection<int>, ManualResetEventSlim>)state).Item2;
          var r = new Random();
          for (int i = 0; i < 3000; i++)
          {
            int result;
            if (!coll.TryTake(out result))
            {
              Console.WriteLine("couldn't take");
            }
            else
            {
              lock (consoleLock)
              {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(" {0} ", result);
                Console.ResetColor();
              }
            }

            Thread.Sleep(r.Next(40));
          }
          wait.Set();
        }, Tuple.Create<BlockingCollection<int>, ManualResetEventSlim>(sharedCollection, events[task]));
        consumer.Start();
      }

      if (!WaitHandle.WaitAll(waits))
        Console.WriteLine("error waiting...");

    }
  }
}
View Code

DictionarySample

using System;
using System.Collections.Generic;

namespace Wrox.ProCSharp.Collections
{
  class Program
  {
    static void Main()
    {
      var employees = new Dictionary<EmployeeId, Employee>(31);

      var idTony = new EmployeeId("C3755");
      var tony = new Employee(idTony, "Tony Stewart", 379025.00m);
      employees.Add(idTony, tony);
      Console.WriteLine(tony);

      var idCarl = new EmployeeId("F3547");
      var carl = new Employee(idCarl, "Carl Edwards", 403466.00m);
      employees.Add(idCarl, carl);
      Console.WriteLine(carl);

      var idKevin = new EmployeeId("C3386");
      var kevin = new Employee(idKevin, "Kevin Harwick", 415261.00m);
      employees.Add(idKevin, kevin);
      Console.WriteLine(kevin);

      var idMatt = new EmployeeId("F3323");
      var matt = new Employee(idMatt, "Matt Kenseth", 1589390.00m);
      employees[idMatt] = matt;
      Console.WriteLine(matt);

      var idBrad = new EmployeeId("D3234");
      var brad = new Employee(idBrad, "Brad Keselowski", 322295.00m);
      employees[idBrad] = brad;
      Console.WriteLine(brad);



      while (true)
      {
        Console.Write("Enter employee id (X to exit)> ");
        var userInput = Console.ReadLine();
        userInput = userInput.ToUpper();
        if (userInput == "X") break;

        EmployeeId id;
        try
        {
          id = new EmployeeId(userInput);


          Employee employee;
          if (!employees.TryGetValue(id, out employee))
          {
            Console.WriteLine("Employee with id {0} does not exist", id);
          }
          else
          {
            Console.WriteLine(employee);
          }
        }
        catch (EmployeeIdException ex)
        {
          Console.WriteLine(ex.Message);
        }
      }

    }
  }
}
View Code
using System;
using System.Diagnostics.Contracts;

namespace Wrox.ProCSharp.Collections
{
  [Serializable]
  public class EmployeeIdException : Exception
  {
    public EmployeeIdException(string message) : base(message) { }
  }

  [Serializable]
  public struct EmployeeId : IEquatable<EmployeeId>
  {
    private readonly char prefix;
    private readonly int number;

    public EmployeeId(string id)
    {
      Contract.Requires<ArgumentNullException>(id != null);

      prefix = (id.ToUpper())[0];
      int numLength = id.Length - 1;
      try
      {
        number = int.Parse(id.Substring(1, numLength > 6 ? 6 : numLength));
      }
      catch (FormatException)
      {
        throw new EmployeeIdException("Invalid EmployeeId format");
      }
    }

    public override string ToString()
    {
      return prefix.ToString() + string.Format("{0,6:000000}", number);
    }

    public override int GetHashCode()
    {
      return (number ^ number << 16) * 0x15051505;
    }

    public bool Equals(EmployeeId other)
    {
      if (other == null) return false;

      return (prefix == other.prefix && number == other.number);
    }

    public override bool Equals(object obj)
    {
      return Equals((EmployeeId)obj);
    }

    public static bool operator ==(EmployeeId left, EmployeeId right)
    {
      return left.Equals(right);
    }

    public static bool operator !=(EmployeeId left, EmployeeId right)
    {
      return !(left == right);
    }
  }

}
View Code
using System;

namespace Wrox.ProCSharp.Collections
{
  [Serializable]
  public class Employee
  {
    private string name;
    private decimal salary;
    private readonly EmployeeId id;

    public Employee(EmployeeId id, string name, decimal salary)
    {
      this.id = id;
      this.name = name;
      this.salary = salary;
    }

    public override string ToString()
    {
      return String.Format("{0}: {1, -20} {2:C}",
            id.ToString(), name, salary);
    }
  }

}
View Code

ImmutableCollectionsSample

using System;
using System.Collections.Generic;
using System.Collections.Immutable;

namespace ImmutableCollectionsSample
{
  class Program
  {
    static void Main(string[] args)
    {
      // ArraySample();
      ListSample();
      Console.ReadKey();
    }

    private static void ListSample()
    {
      List<Account> accounts = new List<Account>() {
        new Account {
          Name = "Scrooge McDuck", 
          Amount = 667377678765m
        },
        new Account {
          Name = "Donald Duck",
          Amount = -200m
        },
       new Account {
         Name = "Ludwig von Drake",
         Amount = 20000m
        }};
      ImmutableList<Account> immutableAccounts = accounts.ToImmutableList();

      ImmutableList<Account>.Builder builder = immutableAccounts.ToBuilder();
      for (int i = 0; i < builder.Count; i++)
      {
        Account a = builder[i];
        if (a.Amount > 0)
        {
          builder.Remove(a);
        }
      }

      ImmutableList<Account> overdrawnAccounts = builder.ToImmutable();


      foreach (var item in overdrawnAccounts)
      {
        Console.WriteLine("{0} {1}", item.Name, item.Amount);
      }

    }

    private static void ArraySample()
    {
      ImmutableArray<string> a1 = ImmutableArray.Create<string>();
      ImmutableArray<string> a2 = a1.Add("Williams");
      ImmutableArray<string> a3 = a2.Add("Ferrari").Add("Mercedes").Add("Red Bull Racing");
      foreach (var item in a3)
      {
        Console.WriteLine(item);
      }

    }
  }
}
View Code
namespace ImmutableCollectionsSample
{
  public class Account
  {
    public string Name { get; set; }
    public decimal Amount { get; set; }
  }
}
View Code

LinkedListSample

using System;
namespace Wrox.ProCSharp.Collections
{
  class Program
  {
    static void Main()
    {
      PriorityDocumentManager pdm = new PriorityDocumentManager();
      pdm.AddDocument(new Document("one", "Sample", 8));
      pdm.AddDocument(new Document("two", "Sample", 3));
      pdm.AddDocument(new Document("three", "Sample", 4));
      pdm.AddDocument(new Document("four", "Sample", 8));
      pdm.AddDocument(new Document("five", "Sample", 1));
      pdm.AddDocument(new Document("six", "Sample", 9));
      pdm.AddDocument(new Document("seven", "Sample", 1));
      pdm.AddDocument(new Document("eight", "Sample", 1));

      pdm.DisplayAllNodes();
      Console.ReadKey();
    }
  }
}
View Code
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;

namespace Wrox.ProCSharp.Collections
{
  public class PriorityDocumentManager
  {
    private readonly LinkedList<Document> documentList;

    // priorities 0.9
    private readonly List<LinkedListNode<Document>> priorityNodes;

    public PriorityDocumentManager()
    {
      documentList = new LinkedList<Document>();

      priorityNodes = new List<LinkedListNode<Document>>(10);
      for (int i = 0; i < 10; i++)
      {
        priorityNodes.Add(new LinkedListNode<Document>(null));
      }
    }

    public void AddDocument(Document d)
    {
      //Contract.Requires<ArgumentNullException>(d != null, "argument d must not be null");
      if (d == null) throw new ArgumentNullException("d");

      AddDocumentToPriorityNode(d, d.Priority);
    }

    private void AddDocumentToPriorityNode(Document doc, int priority)
    {
      //Contract.Requires<ArgumentException>(priority >= 0 && priority < 10, "priority value must be between 0 and 9");
      if (priority > 9 || priority < 0)
          throw new ArgumentException("Priority must be between 0 and 9");

      if (priorityNodes[priority].Value == null)
      {
        --priority;
        if (priority >= 0)
        {
          // check for the next lower priority
          AddDocumentToPriorityNode(doc, priority);
        }
        else // now no priority node exists with the same priority or lower
        // add the new document to the end
        {
          documentList.AddLast(doc);
          priorityNodes[doc.Priority] = documentList.Last;
        }
        return;
      }
      else // a priority node exists
      {
        LinkedListNode<Document> prioNode = priorityNodes[priority];
        if (priority == doc.Priority)
        // priority node with the same priority exists
        {
          documentList.AddAfter(prioNode, doc);

          // set the priority node to the last document with the same priority
          priorityNodes[doc.Priority] = prioNode.Next;
        }
        else // only priority node with a lower priority exists
        {
          // get the first node of the lower priority
          LinkedListNode<Document> firstPrioNode = prioNode;

          while (firstPrioNode.Previous != null &&
             firstPrioNode.Previous.Value.Priority == prioNode.Value.Priority)
          {
            firstPrioNode = prioNode.Previous;
            prioNode = firstPrioNode;
          }

          documentList.AddBefore(firstPrioNode, doc);

          // set the priority node to the new value
          priorityNodes[doc.Priority] = firstPrioNode.Previous;
        }
      }
    }

    public void DisplayAllNodes()
    {
      foreach (Document doc in documentList)
      {
        Console.WriteLine("priority: {0}, title {1}", doc.Priority, doc.Title);
      }
    }

    // returns the document with the highest priority
    // (that's first in the linked list)
    public Document GetDocument()
    {
      Document doc = documentList.First.Value;
      documentList.RemoveFirst();
      return doc;
    }

  }

}
View Code
namespace Wrox.ProCSharp.Collections
{
  public class Document
  {
    public string Title { get; private set; }
    public string Content { get; private set; }
    public byte Priority { get; private set; }

    public Document(string title, string content, byte priority)
    {
      this.Title = title;
      this.Content = content;
      this.Priority = priority;
    }
  }

}
View Code

ListSamples

using System;
using System.Collections.Generic;

namespace Wrox.ProCSharp.Collections
{
  public enum CompareType
  {
    FirstName,
    LastName,
    Country,
    Wins
  }

  public class RacerComparer : IComparer<Racer>
  {
    private CompareType compareType;
    public RacerComparer(CompareType compareType)
    {
      this.compareType = compareType;
    }

    public int Compare(Racer x, Racer y)
    {
      if (x == null && y == null) return 0;
      if (x == null) return -1;
      if (y == null) return 1;

      int result;
      switch (compareType)
      {
        case CompareType.FirstName:
          return string.Compare(x.FirstName, y.FirstName);
        case CompareType.LastName:
          return string.Compare(x.LastName, y.LastName);
        case CompareType.Country:
          result = string.Compare(x.Country, y.Country);
          if (result == 0)
            return string.Compare(x.LastName, y.LastName);
          else
            return result;
        case CompareType.Wins:
          return x.Wins.CompareTo(y.Wins);
        default:
          throw new ArgumentException("Invalid Compare Type");
      }
    }
  }

}
View Code
using System;

namespace Wrox.ProCSharp.Collections
{
  [Serializable]
  public class Racer : IComparable<Racer>, IFormattable
  {
    public int Id { get; private set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Country { get; set; }
    public int Wins { get; set; }

    public Racer(int id, string firstName, string lastName, string country)
      : this(id, firstName, lastName, country, wins: 0)
    {
    }
    public Racer(int id, string firstName, string lastName, string country, int wins)
    {
      this.Id = id;
      this.FirstName = firstName;
      this.LastName = lastName;
      this.Country = country;
      this.Wins = wins;
    }

    public override string ToString()
    {
      return String.Format("{0} {1}", FirstName, LastName);
    }

    public string ToString(string format, IFormatProvider formatProvider)
    {
      if (format == null) format = "N";
      switch (format.ToUpper())
      {
        case null:
        case "N": // name
          return ToString();
        case "F": // first name
          return FirstName;
        case "L": // last name
          return LastName;
        case "W": // Wins
          return String.Format("{0}, Wins: {1}", ToString(), Wins);
        case "C": // Country
          return String.Format("{0}, Country: {1}", ToString(), Country);
        case "A": // All
          return String.Format("{0}, {1} Wins: {2}", ToString(), Country, Wins);
        default:
          throw new FormatException(String.Format(formatProvider,
                "Format {0} is not supported", format));
      }
    }

    public string ToString(string format)
    {
      return ToString(format, null);
    }

    public int CompareTo(Racer other)
    {
      if (other == null) return -1;
      int compare = string.Compare(this.LastName, other.LastName);
      if (compare == 0)
        return string.Compare(this.FirstName, other.FirstName);
      return compare;
    }
  }

}
View Code
using System.Collections.Generic;

namespace Wrox.ProCSharp.Collections
{
    class Program
    {
        static void Main()
        {
            var graham = new Racer(7, "Graham", "Hill", "UK", 14);
            var emerson = new Racer(13, "Emerson", "Fittipaldi", "Brazil", 14);
            var mario = new Racer(16, "Mario", "Andretti", "USA", 12);

            var racers = new List<Racer>(20) { graham, emerson, mario };

            racers.Add(new Racer(24, "Michael", "Schumacher", "Germany", 91));
            racers.Add(new Racer(27, "Mika", "Hakkinen", "Finland", 20));

            racers.AddRange(new Racer[] {
               new Racer(14, "Niki", "Lauda", "Austria", 25),
               new Racer(21, "Alain", "Prost", "France", 51)});

            var racers2 = new List<Racer>(new Racer[] {
               new Racer(12, "Jochen", "Rindt", "Austria", 6),
               new Racer(22, "Ayrton", "Senna", "Brazil", 41) });



        }
    }
}
View Code

LookupSample

using System;

namespace Wrox.ProCSharp.Collections
{
  [Serializable]
  public class Racer : IComparable<Racer>, IFormattable
  {
    public int Id { get; private set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Country { get; set; }
    public int Wins { get; set; }

    public Racer(int id, string firstName, string lastName, string country = null, int wins = 0)
    {
      this.Id = id;
      this.FirstName = firstName;
      this.LastName = lastName;
      this.Country = country;
      this.Wins = wins;
    }

    public override string ToString()
    {
      return String.Format("{0} {1}", FirstName, LastName);
    }

    public string ToString(string format, IFormatProvider formatProvider)
    {
      if (format == null) format = "N";
      switch (format.ToUpper())
      {
        case "N": // name
          return ToString();
        case "F": // first name
          return FirstName;
        case "L": // last name
          return LastName;
        case "W": // Wins
          return String.Format("{0}, Wins: {1}", ToString(), Wins);
        case "C": // Country
          return String.Format("{0}, Country: {1}", ToString(), Country);
        case "A": // All
          return String.Format("{0}, {1} Wins: {2}", ToString(), Country, Wins);
        default:
          throw new FormatException(String.Format(formatProvider,
                "Format {0} is not supported", format));
      }
    }

    public string ToString(string format)
    {
      return ToString(format, null);
    }

    public int CompareTo(Racer other)
    {
      int compare = this.LastName.CompareTo(other.LastName);
      if (compare == 0)
        return this.FirstName.CompareTo(other.FirstName);
      return compare;
    }
  }

}
View Code
using System;
using System.Collections.Generic;
using System.Linq;

namespace Wrox.ProCSharp.Collections
{
  class Program
  {
    static void Main()
    {
      var racers = new List<Racer>();
      racers.Add(new Racer(26, "Jacques", "Villeneuve", "Canada", 11));
      racers.Add(new Racer(18, "Alan", "Jones", "Australia", 12));
      racers.Add(new Racer(11, "Jackie", "Stewart", "United Kingdom", 27));
      racers.Add(new Racer(15, "James", "Hunt", "United Kingdom", 10));
      racers.Add(new Racer(5, "Jack", "Brabham", "Australia", 14));

      var lookupRacers = racers.ToLookup(r => r.Country);

      foreach (Racer r in lookupRacers["Australia"])
      {
        Console.WriteLine(r);
      }

    }
  }
}
View Code

ObservableCollectionSample

using System;
using System.Collections.ObjectModel;

namespace Wrox.ProCSharp.Collections
{
  class Program
  {
    static void Main()
    {
      var data = new ObservableCollection<string>();
      data.CollectionChanged += Data_CollectionChanged;
      data.Add("One");
      data.Add("Two");
      data.Insert(1, "Three");
      data.Remove("One");

    }

    static void Data_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
      Console.WriteLine("action: {0}", e.Action.ToString());

      if (e.OldItems != null)
      {
        Console.WriteLine("starting index for old item(s): {0}", e.OldStartingIndex);
        Console.WriteLine("old item(s):");
        foreach (var item in e.OldItems)
        {
          Console.WriteLine(item);
        }
      }
      if (e.NewItems != null)
      {
        Console.WriteLine("starting index for new item(s): {0}", e.NewStartingIndex);
        Console.WriteLine("new item(s): ");
        foreach (var item in e.NewItems)
        {
          Console.WriteLine(item);
        }
      }


      Console.WriteLine();

    }
  }
}
View Code

PiplelineSample

using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;

namespace Wrox.ProCSharp.Collections
{
  class Program
  {
    static void Main(string[] args)
    {
      StartPipeline();
      Console.ReadLine();
    }

    private static async void StartPipeline()
    {
      var fileNames = new BlockingCollection<string>();
      var lines = new BlockingCollection<string>();
      var words = new ConcurrentDictionary<string, int>();
      var items = new BlockingCollection<Info>();
      var coloredItems = new BlockingCollection<Info>();

      Task t1 = PipelineStages.ReadFilenamesAsync(@"../../..", fileNames);
      ConsoleHelper.WriteLine("started stage 1");
      Task t2 = PipelineStages.LoadContentAsync(fileNames, lines);
      ConsoleHelper.WriteLine("started stage 2");
      Task t3 = PipelineStages.ProcessContentAsync(lines, words);
      await Task.WhenAll(t1, t2, t3);
      ConsoleHelper.WriteLine("stages 1, 2, 3 completed");

      Task t4 = PipelineStages.TransferContentAsync(words, items);
      Task t5 = PipelineStages.AddColorAsync(items, coloredItems);
      Task t6 = PipelineStages.ShowContentAsync(coloredItems);
      ConsoleHelper.WriteLine("stages 4, 5, 6 started");

      await Task.WhenAll(t4, t5, t6);

      ConsoleHelper.WriteLine("all stages finished");
    }
  }
}
View Code
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace Wrox.ProCSharp.Collections
{
  public static class PipelineStages
  {
    public static Task ReadFilenamesAsync(string path, BlockingCollection<string> output)
    {
      return Task.Run(() =>
        {
          foreach (string filename in Directory.EnumerateFiles(path, "*.cs", SearchOption.AllDirectories))
          {
            output.Add(filename);
            ConsoleHelper.WriteLine(string.Format("stage 1: added {0}", filename));
          }
          output.CompleteAdding();
        });
    }

    public static async Task LoadContentAsync(BlockingCollection<string> input, BlockingCollection<string> output)
    {
      foreach (var filename in input.GetConsumingEnumerable())
      {
        using (FileStream stream = File.OpenRead(filename))
        {
          var reader = new StreamReader(stream);
          string line = null;
          while ((line = await reader.ReadLineAsync()) != null)
          {
            output.Add(line);
            ConsoleHelper.WriteLine(string.Format("stage 2: added {0}", line));
          }
        }
      }
      output.CompleteAdding();
    }

    public static Task ProcessContentAsync(BlockingCollection<string> input, ConcurrentDictionary<string, int> output)
    {
      return Task.Run(() =>
        {
          foreach (var line in input.GetConsumingEnumerable())
          {
            string[] words = line.Split(' ', ';', '	', '{', '}', '(', ')', ':', ',', '"');
            foreach (var word in words.Where(w => !string.IsNullOrEmpty(w)))
            {
              output.AddOrIncrementValue(word);
              ConsoleHelper.WriteLine(string.Format("stage 3: added {0}", word));
            }
          }
        });
    }

    public static Task TransferContentAsync(ConcurrentDictionary<string, int> input, BlockingCollection<Info> output)
    {
      return Task.Run(() =>
        {
          foreach (var word in input.Keys)
          {
            int value;
            if (input.TryGetValue(word, out value))
            {
              var info = new Info { Word = word, Count = value };
              output.Add(info);
              ConsoleHelper.WriteLine(string.Format("stage 4: added {0}", info));
            }
          }
          output.CompleteAdding();
        });
    }

    public static Task AddColorAsync(BlockingCollection<Info> input, BlockingCollection<Info> output)
    {
      return Task.Run(() =>
        {
          foreach (var item in input.GetConsumingEnumerable())
          {
            if (item.Count > 40)
            {
              item.Color = "Red";
            }
            else if (item.Count > 20)
            {
              item.Color = "Yellow";
            }
            else
            {
              item.Color = "Green";
            }
            output.Add(item);
            ConsoleHelper.WriteLine(string.Format("stage 5: added color {1} to {0}", item, item.Color));
          }
          output.CompleteAdding();
        });
    }

    public static Task ShowContentAsync(BlockingCollection<Info> input)
    {
      return Task.Run(() =>
        {
          foreach (var item in input.GetConsumingEnumerable())
          {
            ConsoleHelper.WriteLine(string.Format("stage 6: {0}", item), item.Color);
          }
        });
    }
  }
}
View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Wrox.ProCSharp.Collections
{
  public class Info
  {
    public string Word { get; set; }
    public int Count { get; set; }
    public string Color { get; set; }

    public override string ToString()
    {
      return String.Format("{0} times: {1}", Count, Word);
    }
  }
}
View Code
using System;

namespace Wrox.ProCSharp.Collections
{
  public class ConsoleHelper
  {
    private static object syncOutput = new object();

    public static void WriteLine(string message)
    {
      lock (syncOutput)
      {
        Console.WriteLine(message);
      }
    }

    public static void WriteLine(string message, string color)
    {
      lock (syncOutput)
      {
        Console.ForegroundColor = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), color);
        Console.WriteLine(message);
        Console.ResetColor();
      }
    }
  }
}
View Code
using System.Collections.Concurrent;

namespace Wrox.ProCSharp.Collections
{
  public static class ConcurrentDictionaryExtension
  {
    public static void AddOrIncrementValue(this ConcurrentDictionary<string, int> dict, string key)
    {
      bool success = false;
      while (!success)
      {
        int value;
        if (dict.TryGetValue(key, out value))
        {
          if (dict.TryUpdate(key, value + 1, value))
          {
            success = true;
          }
        }
        else
        {
          if (dict.TryAdd(key, 1))
          {
            success = true;
          }
        }
      }
    }
  }
}
View Code

QueueSample

using System;
using System.Threading;

namespace Wrox.ProCSharp.Collections
{
    class Program
    {
        static void Main()
        {
            var dm = new DocumentManager();

            ProcessDocuments.Start(dm);

            // Create documents and add them to the DocumentManager
            for (int i = 0; i < 1000; i++)
            {
                Document doc = new Document("Doc " + i.ToString(), "content");
                dm.AddDocument(doc);
                Console.WriteLine("Added document {0}", doc.Title);
                Thread.Sleep(new Random().Next(20));
            }
            Console.ReadKey();
        }
    }
}
View Code
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Wrox.ProCSharp.Collections
{
  public class ProcessDocuments
  {
    public static void Start(DocumentManager dm)
    {
      Task.Factory.StartNew(new ProcessDocuments(dm).Run);
    }

    protected ProcessDocuments(DocumentManager dm)
    {
      if (dm == null)
        throw new ArgumentNullException("dm");
      documentManager = dm;
    }

    private DocumentManager documentManager;

    protected void Run()
    {
      while (true)
      {
        if (documentManager.IsDocumentAvailable)
        {
          Document doc = documentManager.GetDocument();
          Console.WriteLine("Processing document {0}", doc.Title);
        }
        Thread.Sleep(new Random().Next(20));
      }
    }
  }

}
View Code
using System.Collections.Generic;

namespace Wrox.ProCSharp.Collections
{
  public class DocumentManager
  {
    private readonly Queue<Document> documentQueue = new Queue<Document>();

    public void AddDocument(Document doc)
    {
      lock (this)
      {
        documentQueue.Enqueue(doc);
      }
    }

    public Document GetDocument()
    {
      Document doc = null;
      lock (this)
      {
        doc = documentQueue.Dequeue();
      }
      return doc;
    }

    public bool IsDocumentAvailable
    {
      get
      {
        return documentQueue.Count > 0;
      }
    }
  }

}
View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Wrox.ProCSharp.Collections
{
  public class Document
  {
    public string Title { get; private set; }
    public string Content { get; private set; }

    public Document(string title, string content)
    {
      this.Title = title;
      this.Content = content;
    }
  }

}
View Code

SetSample

using System;
using System.Collections.Generic;

namespace SetSample
{
  class Program
  {
    static void Main()
    {
      var companyTeams = new HashSet<string>() { "Ferrari", "McLaren", "Mercedes" };
      var traditionalTeams = new HashSet<string>() { "Ferrari", "McLaren" };
      var privateTeams = new HashSet<string>() { "Red Bull", "Lotus", "Toro Rosso", "Force India", "Sauber" };

      if (privateTeams.Add("Williams"))
        Console.WriteLine("Williams added");
      if (!companyTeams.Add("McLaren"))
        Console.WriteLine("McLaren was already in this set");

      if (traditionalTeams.IsSubsetOf(companyTeams))
      {
        Console.WriteLine("traditionalTeams is subset of companyTeams");
      }

      if (companyTeams.IsSupersetOf(traditionalTeams))
      {
        Console.WriteLine("companyTeams is a superset of traditionalTeams");
      }


      traditionalTeams.Add("Williams");
      if (privateTeams.Overlaps(traditionalTeams))
      {
        Console.WriteLine("At least one team is the same with the traditional " +
              "and private teams");
      }

      var allTeams = new SortedSet<string>(companyTeams);
      allTeams.UnionWith(privateTeams);
      allTeams.UnionWith(traditionalTeams);

      Console.WriteLine();
      Console.WriteLine("all teams");
      foreach (var team in allTeams)
      {
        Console.WriteLine(team);
      }

      allTeams.ExceptWith(privateTeams);
      Console.WriteLine();
      Console.WriteLine("no private team left");
      foreach (var team in allTeams)
      {
        Console.WriteLine(team);
      }




    }
  }
}
View Code

SortedListSample

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Wrox.ProCSharp.Collections
{
  class Program
  {
    static void Main()
    {
      var books = new SortedList<string, string>();
      books.Add("Professional WPF Programming", "978–0–470–04180–2");
      books.Add("Professional ASP.NET MVC 3", "978–1–1180–7658–3");

      books["Beginning Visual C# 2010"] = "978–0–470-50226-6";
      books["Professional C# 4 and .NET 4"] = "978–0–470–50225–9";

      foreach (KeyValuePair<string, string> book in books)
      {
        Console.WriteLine("{0}, {1}", book.Key, book.Value);
      }

      foreach (string isbn in books.Values)
      {
        Console.WriteLine(isbn);
      }

      foreach (string title in books.Keys)
      {
        Console.WriteLine(title);
      }

      {
        string isbn;
        string title = "Professional C# 7.0";
        if (!books.TryGetValue(title, out isbn))
        {
          Console.WriteLine("{0} not found", title);
        }
      }



    }
  }
}
View Code

StackSample

using System;
using System.Collections.Generic;

namespace Wrox.ProCSharp.Collections
{
    class Program
    {
        static void Main()
        {
            var alphabet = new Stack<char>();
            alphabet.Push('A');
            alphabet.Push('B');
            alphabet.Push('C');

            Console.Write("First iteration: ");
            foreach (char item in alphabet)
            {
                Console.Write(item);
            }
            Console.WriteLine();

            Console.Write("Second iteration: ");
            while (alphabet.Count > 0)
            {
                Console.Write(alphabet.Pop());
            }
            Console.WriteLine();


        }
    }
}
View Code
原文地址:https://www.cnblogs.com/liuslayer/p/7086090.html