Advertisement
Filkolev

Scoreboard

Sep 13th, 2015
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 24.25 KB | None | 0 0
  1. namespace Scoreboard
  2. {
  3.     using System;
  4.     using System.Collections;
  5.     using System.Collections.Generic;
  6.     using System.Linq;
  7.     using System.Text;
  8.  
  9.     using Wintellect.PowerCollections;
  10.  
  11.     public class ScoreboardMain
  12.     {
  13.         public static void Main(string[] args)
  14.         {
  15.             Scoreboard scoreboard = new Scoreboard();
  16.  
  17.             string command = Console.ReadLine();
  18.  
  19.             while (command != "End")
  20.             {
  21.                 if (string.IsNullOrWhiteSpace(command))
  22.                 {
  23.                     command = Console.ReadLine();
  24.                     continue;
  25.                 }
  26.  
  27.                 var commandParams = command.Split();
  28.                 string commandResult = null;
  29.  
  30.                 switch (commandParams[0])
  31.                 {
  32.                     case "RegisterUser":
  33.                         commandResult = scoreboard.RegisterUser(commandParams);
  34.                         break;
  35.                     case "RegisterGame":
  36.                         commandResult = scoreboard.RegisterGame(commandParams);
  37.                         break;
  38.                     case "AddScore":
  39.                         commandResult = scoreboard.AddScore(commandParams);
  40.                         break;
  41.                     case "ShowScoreboard":
  42.                         commandResult = scoreboard.ShowScoreboard(commandParams);
  43.                         break;
  44.                     case "ListGamesByPrefix":
  45.                         commandResult = scoreboard.ListGamesByPrefix(commandParams);
  46.                         break;
  47.                     case "DeleteGame":
  48.                         commandResult = scoreboard.DeleteGame(commandParams);
  49.                         break;
  50.                 }
  51.  
  52.                 Console.WriteLine(commandResult);
  53.  
  54.                 command = Console.ReadLine();
  55.             }
  56.         }
  57.     }
  58.  
  59.     public class Game
  60.     {
  61.         public string Name { get; set; }
  62.  
  63.         public string Password { get; set; }
  64.     }
  65.  
  66.     public class Score : IComparable<Score>
  67.     {
  68.         public string Username { get; set; }
  69.  
  70.         public int Value { get; set; }
  71.  
  72.         public int CompareTo(Score other)
  73.         {
  74.             int result = other.Value.CompareTo(this.Value);
  75.  
  76.             if (result == 0)
  77.             {
  78.                 result = this.Username.CompareTo(other.Username);
  79.             }
  80.  
  81.             return result;
  82.         }
  83.     }
  84.  
  85.     public class User
  86.     {
  87.         public string Username { get; set; }
  88.  
  89.         public string Password { get; set; }
  90.     }
  91.  
  92.     public class Scoreboard
  93.     {
  94.         private Dictionary<string, User> users = new Dictionary<string, User>();
  95.         private Dictionary<string, Game> games = new Dictionary<string, Game>();
  96.         private Trie<bool> gameNames = new Trie<bool>();
  97.         private Dictionary<Game, OrderedBag<Score>> scores = new Dictionary<Game, OrderedBag<Score>>();
  98.  
  99.         public string RegisterUser(string[] parameters)
  100.         {
  101.             if (this.users.ContainsKey(parameters[1]))
  102.             {
  103.                 return "Duplicated user";
  104.             }
  105.  
  106.             var user = new User { Username = parameters[1], Password = parameters[2] };
  107.             this.users.Add(user.Username, user);
  108.  
  109.             return "User registered";
  110.         }
  111.  
  112.         public string RegisterGame(string[] parameters)
  113.         {
  114.             if (this.games.ContainsKey(parameters[1]))
  115.             {
  116.                 return "Duplicated game";
  117.             }
  118.  
  119.             var game = new Game { Name = parameters[1], Password = parameters[2] };
  120.             this.games.Add(game.Name, game);
  121.             this.gameNames.Add(game.Name, true);
  122.             this.scores.Add(game, new OrderedBag<Score>());
  123.  
  124.             return "Game registered";
  125.         }
  126.  
  127.         public string AddScore(string[] parameters)
  128.         {
  129.             User user;
  130.             this.users.TryGetValue(parameters[1], out user);
  131.  
  132.             if (user == null || user.Password != parameters[2])
  133.             {
  134.                 return "Cannot add score";
  135.             }
  136.  
  137.             Game game;
  138.             this.games.TryGetValue(parameters[3], out game);
  139.  
  140.             if (game == null || game.Password != parameters[4])
  141.             {
  142.                 return "Cannot add score";
  143.             }
  144.  
  145.             int score = int.Parse(parameters[5]);
  146.  
  147.             this.scores[game].Add(new Score { Username = user.Username, Value = score });
  148.  
  149.             return "Score added";
  150.         }
  151.  
  152.         public string ShowScoreboard(string[] parameters)
  153.         {
  154.             Game game;
  155.             this.games.TryGetValue(parameters[1], out game);
  156.  
  157.             if (game == null)
  158.             {
  159.                 return "Game not found";
  160.             }
  161.  
  162.             var topScores = this.scores[game].Take(10).ToList();
  163.             var scoresCount = topScores.Count;
  164.  
  165.             if (scoresCount == 0)
  166.             {
  167.                 return "No score";
  168.             }
  169.  
  170.             StringBuilder result = new StringBuilder();
  171.  
  172.             for (int i = 1; i <= scoresCount; i++)
  173.             {
  174.                 result.AppendLine($"#{i} {topScores[i - 1].Username} {topScores[i - 1].Value}");
  175.             }
  176.  
  177.             return result.ToString().TrimEnd();
  178.         }
  179.  
  180.         public string ListGamesByPrefix(string[] parameters)
  181.         {
  182.             var gamesWithPrefix = this.gameNames.GetByPrefix(parameters[1]).Select(n => n.Key).Take(10);
  183.  
  184.             if (gamesWithPrefix.Any())
  185.             {
  186.                 return string.Join(", ", gamesWithPrefix);
  187.             }
  188.  
  189.             return "No matches";
  190.         }
  191.  
  192.         public string DeleteGame(string[] parameters)
  193.         {
  194.             Game game;
  195.             this.games.TryGetValue(parameters[1], out game);
  196.  
  197.             if (game == null || game.Password != parameters[2])
  198.             {
  199.                 return "Cannot delete game";
  200.             }
  201.  
  202.             this.games.Remove(game.Name);
  203.             this.gameNames.Remove(game.Name);
  204.             this.scores.Remove(game);
  205.  
  206.             return "Game deleted";
  207.         }
  208.     }
  209.  
  210.  
  211.  
  212.     /// <summary>
  213.     /// Implementation of "trie" data structure.
  214.     /// </summary>
  215.     /// <typeparam name="TValue">The type of values in the trie.</typeparam>
  216.     public class Trie<TValue> : IDictionary<string, TValue>
  217.     {
  218.         private readonly TrieNode root;
  219.  
  220.         private int count;
  221.  
  222.         /// <summary>
  223.         /// Initializes a new instance of the <see cref="Trie{TValue}"/>.
  224.         /// </summary>
  225.         /// <param name="comparer">Comparer.</param>
  226.         public Trie(IEqualityComparer<char> comparer)
  227.         {
  228.             root = new TrieNode(char.MinValue, comparer);
  229.         }
  230.  
  231.         /// <summary>
  232.         /// Initializes a new instance of the <see cref="Trie{TValue}"/>.
  233.         /// </summary>
  234.         public Trie()
  235.             : this(EqualityComparer<char>.Default)
  236.         {
  237.         }
  238.  
  239.         /// <summary>
  240.         /// Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
  241.         /// </summary>
  242.         /// <returns>
  243.         /// The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
  244.         /// </returns>
  245.         public int Count
  246.         {
  247.             get
  248.             {
  249.                 return count;
  250.             }
  251.         }
  252.  
  253.         /// <summary>
  254.         /// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the keys of the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
  255.         /// </summary>
  256.         /// <returns>
  257.         /// An <see cref="T:System.Collections.Generic.ICollection`1"/> containing the keys of the object that implements <see cref="T:System.Collections.Generic.IDictionary`2"/>.
  258.         /// </returns>
  259.         public ICollection<string> Keys
  260.         {
  261.             get
  262.             {
  263.                 return GetAllNodes().Select(n => n.Key).ToArray();
  264.             }
  265.         }
  266.  
  267.         /// <summary>
  268.         /// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the values in the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
  269.         /// </summary>
  270.         /// <returns>
  271.         /// An <see cref="T:System.Collections.Generic.ICollection`1"/> containing the values in the object that implements <see cref="T:System.Collections.Generic.IDictionary`2"/>.
  272.         /// </returns>
  273.         public ICollection<TValue> Values
  274.         {
  275.             get
  276.             {
  277.                 return GetAllNodes().Select(n => n.Value).ToArray();
  278.             }
  279.         }
  280.  
  281.         bool ICollection<KeyValuePair<string, TValue>>.IsReadOnly
  282.         {
  283.             get
  284.             {
  285.                 return false;
  286.             }
  287.         }
  288.  
  289.         /// <summary>
  290.         /// Gets or sets the element with the specified key.
  291.         /// </summary>
  292.         /// <returns>
  293.         /// The element with the specified key.
  294.         /// </returns>
  295.         /// <param name="key">The key of the element to get or set.</param>
  296.         /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null.</exception>
  297.         /// <exception cref="T:System.Collections.Generic.KeyNotFoundException">The property is retrieved and <paramref name="key"/> is not found.</exception>
  298.         public TValue this[string key]
  299.         {
  300.             get
  301.             {
  302.                 TValue value;
  303.  
  304.                 if (!TryGetValue(key, out value))
  305.                 {
  306.                     throw new KeyNotFoundException("The given charKey was not present in the trie.");
  307.                 }
  308.  
  309.                 return value;
  310.             }
  311.  
  312.             set
  313.             {
  314.                 TrieNode node;
  315.  
  316.                 if (TryGetNode(key, out node))
  317.                 {
  318.                     SetTerminalNode(node, value);
  319.                 }
  320.                 else
  321.                 {
  322.                     Add(key, value);
  323.                 }
  324.             }
  325.         }
  326.  
  327.         /// <summary>
  328.         /// Adds an element with the provided charKey and value to the <see cref="Trie{TValue}"/>.
  329.         /// </summary>
  330.         /// <param name="key">The object to use as the charKey of the element to add.</param>
  331.         /// <param name="value">The object to use as the value of the element to add.</param>
  332.         /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null.</exception>
  333.         /// <exception cref="T:System.ArgumentException">An element with the same charKey already exists in the <see cref="Trie{TValue}"/>.</exception>
  334.         public void Add(string key, TValue value)
  335.         {
  336.             if (key == null)
  337.             {
  338.                 throw new ArgumentNullException("key");
  339.             }
  340.  
  341.             var node = root;
  342.  
  343.             foreach (var c in key)
  344.             {
  345.                 node = node.Add(c);
  346.             }
  347.  
  348.             if (node.IsTerminal)
  349.             {
  350.                 throw new ArgumentException(string.Format("An element with the same charKey already exists: '{0}'", key), "key");
  351.             }
  352.  
  353.             SetTerminalNode(node, value);
  354.  
  355.             count++;
  356.         }
  357.  
  358.         /// <summary>
  359.         /// Adds an item to the <see cref="Trie{TValue}"/>.
  360.         /// </summary>
  361.         /// <param name="item">The object to add to the <see cref="Trie{TValue}"/>.</param>
  362.         /// <exception cref="T:System.ArgumentException">An element with the same charKey already exists in the <see cref="Trie{TValue}"/>.</exception>
  363.         public void Add(TrieEntry<TValue> item)
  364.         {
  365.             Add(item.Key, item.Value);
  366.         }
  367.  
  368.         /// <summary>
  369.         /// Adds the elements of the specified collection to the <see cref="Trie{TValue}"/>.
  370.         /// </summary>
  371.         /// <param name="collection">The collection whose elements should be added to the <see cref="Trie{TValue}"/>. The items should have unique keys.</param>
  372.         /// <exception cref="T:System.ArgumentException">An element with the same charKey already exists in the <see cref="Trie{TValue}"/>.</exception>
  373.         public void AddRange(IEnumerable<TrieEntry<TValue>> collection)
  374.         {
  375.             foreach (var item in collection)
  376.             {
  377.                 Add(item.Key, item.Value);
  378.             }
  379.         }
  380.  
  381.         /// <summary>
  382.         /// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
  383.         /// </summary>
  384.         /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. </exception>
  385.         public void Clear()
  386.         {
  387.             root.Clear();
  388.             count = 0;
  389.         }
  390.  
  391.         /// <summary>
  392.         /// Determines whether the <see cref="T:System.Collections.Generic.IDictionary`2"/> contains an element with the specified charKey.
  393.         /// </summary>
  394.         /// <returns>
  395.         /// true if the <see cref="T:System.Collections.Generic.IDictionary`2"/> contains an element with the charKey; otherwise, false.
  396.         /// </returns>
  397.         /// <param name="key">The charKey to locate in the <see cref="T:System.Collections.Generic.IDictionary`2"/>.</param>
  398.         /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null.</exception>
  399.         public bool ContainsKey(string key)
  400.         {
  401.             TValue value;
  402.  
  403.             return TryGetValue(key, out value);
  404.         }
  405.  
  406.         /// <summary>
  407.         /// Gets items by key prefix.
  408.         /// </summary>
  409.         /// <param name="prefix">Key prefix.</param>
  410.         /// <returns>Collection of <see cref="TrieEntry{TValue}"/> items which have key with specified key.</returns>
  411.         public IEnumerable<TrieEntry<TValue>> GetByPrefix(string prefix)
  412.         {
  413.             var node = root;
  414.  
  415.             foreach (var item in prefix)
  416.             {
  417.                 if (!node.TryGetNode(item, out node))
  418.                 {
  419.                     return Enumerable.Empty<TrieEntry<TValue>>();
  420.                 }
  421.             }
  422.  
  423.             return node.GetByPrefix();
  424.         }
  425.  
  426.         /// <summary>
  427.         /// Returns an enumerator that iterates through the collection.
  428.         /// </summary>
  429.         /// <returns>
  430.         /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
  431.         /// </returns>
  432.         /// <filterpriority>1</filterpriority>
  433.         public IEnumerator<KeyValuePair<string, TValue>> GetEnumerator()
  434.         {
  435.             return GetAllNodes().Select(n => new KeyValuePair<string, TValue>(n.Key, n.Value)).GetEnumerator();
  436.         }
  437.  
  438.         /// <summary>
  439.         /// Removes the element with the specified charKey from the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
  440.         /// </summary>
  441.         /// <returns>
  442.         /// true if the element is successfully removed; otherwise, false.  This method also returns false if <paramref name="key"/> was not found in the original <see cref="T:System.Collections.Generic.IDictionary`2"/>.
  443.         /// </returns>
  444.         /// <param name="key">The charKey of the element to remove.</param>
  445.         /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null.</exception>
  446.         /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IDictionary`2"/> is read-only.</exception>
  447.         public bool Remove(string key)
  448.         {
  449.             if (key == null)
  450.             {
  451.                 throw new ArgumentNullException("key");
  452.             }
  453.  
  454.             TrieNode node;
  455.  
  456.             if (!TryGetNode(key, out node))
  457.             {
  458.                 return false;
  459.             }
  460.  
  461.             if (!node.IsTerminal)
  462.             {
  463.                 return false;
  464.             }
  465.  
  466.             RemoveNode(node);
  467.  
  468.             return true;
  469.         }
  470.  
  471.         /// <summary>
  472.         /// Gets the value associated with the specified key.
  473.         /// </summary>
  474.         /// <returns>
  475.         /// true if the object that implements <see cref="T:System.Collections.Generic.IDictionary`2"/> contains an element with the specified key; otherwise, false.
  476.         /// </returns>
  477.         /// <param name="key">The key whose value to get.</param>
  478.         /// <param name="value">When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized.</param>
  479.         /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null.</exception>
  480.         public bool TryGetValue(string key, out TValue value)
  481.         {
  482.             if (key == null)
  483.             {
  484.                 throw new ArgumentNullException("key");
  485.             }
  486.  
  487.             TrieNode node;
  488.             value = default(TValue);
  489.  
  490.             if (!TryGetNode(key, out node))
  491.             {
  492.                 return false;
  493.             }
  494.  
  495.             if (!node.IsTerminal)
  496.             {
  497.                 return false;
  498.             }
  499.  
  500.             value = node.Value;
  501.  
  502.             return true;
  503.         }
  504.  
  505.         void ICollection<KeyValuePair<string, TValue>>.Add(KeyValuePair<string, TValue> item)
  506.         {
  507.             Add(item.Key, item.Value);
  508.         }
  509.  
  510.         bool ICollection<KeyValuePair<string, TValue>>.Contains(KeyValuePair<string, TValue> item)
  511.         {
  512.             TrieNode node;
  513.  
  514.             if (!TryGetNode(item.Key, out node))
  515.             {
  516.                 return false;
  517.             }
  518.  
  519.             return node.IsTerminal && EqualityComparer<TValue>.Default.Equals(node.Value, item.Value);
  520.         }
  521.  
  522.         void ICollection<KeyValuePair<string, TValue>>.CopyTo(KeyValuePair<string, TValue>[] array, int arrayIndex)
  523.         {
  524.             Array.Copy(GetAllNodes().Select(n => new KeyValuePair<string, TValue>(n.Key, n.Value)).ToArray(), 0, array, arrayIndex, Count);
  525.         }
  526.  
  527.         IEnumerator IEnumerable.GetEnumerator()
  528.         {
  529.             return GetEnumerator();
  530.         }
  531.  
  532.         bool ICollection<KeyValuePair<string, TValue>>.Remove(KeyValuePair<string, TValue> item)
  533.         {
  534.             TrieNode node;
  535.  
  536.             if (!TryGetNode(item.Key, out node))
  537.             {
  538.                 return false;
  539.             }
  540.  
  541.             if (!node.IsTerminal)
  542.             {
  543.                 return false;
  544.             }
  545.  
  546.             if (!EqualityComparer<TValue>.Default.Equals(node.Value, item.Value))
  547.             {
  548.                 return false;
  549.             }
  550.  
  551.             RemoveNode(node);
  552.  
  553.             return true;
  554.         }
  555.  
  556.         private static void SetTerminalNode(TrieNode node, TValue value)
  557.         {
  558.             node.IsTerminal = true;
  559.             node.Value = value;
  560.         }
  561.  
  562.         private IEnumerable<TrieNode> GetAllNodes()
  563.         {
  564.             return root.GetAllNodes();
  565.         }
  566.  
  567.         private void RemoveNode(TrieNode node)
  568.         {
  569.             node.Remove();
  570.             count--;
  571.         }
  572.  
  573.         private bool TryGetNode(string key, out TrieNode node)
  574.         {
  575.             node = root;
  576.  
  577.             foreach (var c in key)
  578.             {
  579.                 if (!node.TryGetNode(c, out node))
  580.                 {
  581.                     return false;
  582.                 }
  583.             }
  584.  
  585.             return true;
  586.         }
  587.  
  588.         /// <summary>
  589.         /// <see cref="Trie{TValue}"/>'s node.
  590.         /// </summary>
  591.         private sealed class TrieNode
  592.         {
  593.             private readonly SortedDictionary<char, TrieNode> children;
  594.  
  595.             private readonly IEqualityComparer<char> comparer;
  596.  
  597.             private readonly char keyChar;
  598.  
  599.             internal TrieNode(char keyChar, IEqualityComparer<char> comparer)
  600.             {
  601.                 this.keyChar = keyChar;
  602.                 this.comparer = comparer;
  603.                 children = new SortedDictionary<char, TrieNode>();
  604.             }
  605.  
  606.             internal bool IsTerminal { get; set; }
  607.  
  608.             internal string Key
  609.             {
  610.                 get
  611.                 {
  612.                     ////var result = new StringBuilder().Append(keyChar);
  613.  
  614.                     ////TrieNode node = this;
  615.  
  616.                     ////while ((node = node.Parent).Parent != null)
  617.                     ////{
  618.                     ////    result.Insert(0, node.keyChar);
  619.                     ////}
  620.  
  621.                     ////return result.ToString();
  622.  
  623.                     var stack = new Stack<char>();
  624.                     stack.Push(keyChar);
  625.  
  626.                     TrieNode node = this;
  627.  
  628.                     while ((node = node.Parent).Parent != null)
  629.                     {
  630.                         stack.Push(node.keyChar);
  631.                     }
  632.  
  633.                     return new string(stack.ToArray());
  634.                 }
  635.             }
  636.  
  637.             internal TValue Value { get; set; }
  638.  
  639.             private TrieNode Parent { get; set; }
  640.  
  641.             internal TrieNode Add(char key)
  642.             {
  643.                 TrieNode childNode;
  644.  
  645.                 if (!children.TryGetValue(key, out childNode))
  646.                 {
  647.                     childNode = new TrieNode(key, comparer)
  648.                     {
  649.                         Parent = this
  650.                     };
  651.  
  652.                     children.Add(key, childNode);
  653.                 }
  654.  
  655.                 return childNode;
  656.             }
  657.  
  658.             internal void Clear()
  659.             {
  660.                 children.Clear();
  661.             }
  662.  
  663.             internal IEnumerable<TrieNode> GetAllNodes()
  664.             {
  665.                 foreach (var child in children)
  666.                 {
  667.                     if (child.Value.IsTerminal)
  668.                     {
  669.                         yield return child.Value;
  670.                     }
  671.  
  672.                     foreach (var item in child.Value.GetAllNodes())
  673.                     {
  674.                         if (item.IsTerminal)
  675.                         {
  676.                             yield return item;
  677.                         }
  678.                     }
  679.                 }
  680.             }
  681.  
  682.             internal IEnumerable<TrieEntry<TValue>> GetByPrefix()
  683.             {
  684.                 if (IsTerminal)
  685.                 {
  686.                     yield return new TrieEntry<TValue>(Key, Value);
  687.                 }
  688.  
  689.                 foreach (var item in children)
  690.                 {
  691.                     foreach (var element in item.Value.GetByPrefix())
  692.                     {
  693.                         yield return element;
  694.                     }
  695.                 }
  696.             }
  697.  
  698.             internal void Remove()
  699.             {
  700.                 IsTerminal = false;
  701.  
  702.                 if (children.Count == 0 && Parent != null)
  703.                 {
  704.                     Parent.children.Remove(keyChar);
  705.  
  706.                     if (!Parent.IsTerminal)
  707.                     {
  708.                         Parent.Remove();
  709.                     }
  710.                 }
  711.             }
  712.  
  713.             internal bool TryGetNode(char key, out TrieNode node)
  714.             {
  715.                 return children.TryGetValue(key, out node);
  716.             }
  717.         }
  718.     }
  719.  
  720.     /// <summary>
  721.     /// Defines a key/value pair that can be set or retrieved from <see cref="Trie{TValue}"/>.
  722.     /// </summary>
  723.     public struct TrieEntry<TValue>
  724.     {
  725.         /// <summary>
  726.         /// Initializes a new instance of the <see cref="TrieEntry{TValue}"/> structure with the specified key and value.
  727.         /// </summary>
  728.         /// <param name="key">The <see cref="string"/> object defined in each key/value pair.</param>
  729.         /// <param name="value">The definition associated with key.</param>
  730.         public TrieEntry(string key, TValue value)
  731.             : this()
  732.         {
  733.             Key = key;
  734.             Value = value;
  735.         }
  736.  
  737.         /// <summary>
  738.         /// Gets the key in the key/value pair.
  739.         /// </summary>
  740.         public string Key { get; private set; }
  741.  
  742.         /// <summary>
  743.         /// Gets the value in the key/value pair.
  744.         /// </summary>
  745.         public TValue Value { get; private set; }
  746.  
  747.         /// <summary>
  748.         /// Returns the fully qualified type name of this instance.
  749.         /// </summary>
  750.         /// <returns>
  751.         /// A <see cref="T:System.String"/> containing a fully qualified type name.
  752.         /// </returns>
  753.         /// <filterpriority>2</filterpriority>
  754.         public override string ToString()
  755.         {
  756.             return string.Format("[{0}, {1}]", Key, Value);
  757.         }
  758.     }
  759. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement