namespace ConsoleApplication1
{
  using System;
	using System.Collections.Generic;
	using System.Diagnostics;
	using System.Text;
	using System.Text.RegularExpressions;

	public class Program
	{
		private const string TestData = "Some Random Placé & Some' Chars. ";
		private const int Iterations = 1000000;

		public static void Main(string[] args)
		{
			Test(BenchmarkOverhead);
			Test(StringCleanA);
			Test(StringCleanB);
			Test(StringCleanC);
			//Test(StringCleanD);

			Test(BenchmarkOverhead);
			Test(StringCleanA);
			Test(StringCleanB);
			Test(StringCleanC);
			//Test(StringCleanD);

			Test(BenchmarkOverhead);
			Test(StringCleanA);
			Test(StringCleanB);
			Test(StringCleanC);
			//Test(StringCleanD);

			Test(BenchmarkOverhead);
			Test(StringCleanA);
			Test(StringCleanB);
			Test(StringCleanC);
			//Test(StringCleanD);
			Console.ReadLine();
		}

		private static void Test(Func<string, bool> function)
		{
			Console.Write("{0}... ", function.Method.Name);
			Stopwatch sw = Stopwatch.StartNew();
			for (int i = 0; i < Iterations; i++)
			{
				function(TestData);
			}
			sw.Stop();
			Console.WriteLine(" {0}ms", sw.ElapsedMilliseconds);
			GC.Collect();
		}

		private static bool BenchmarkOverhead(string str)
		{
			return true;
		}

		private static bool StringCleanA(string str)
		{
			StringExtensionA.Clean(str);
			return true;
		}

		private static bool StringCleanB(string str)
		{
			StringExtensionB.Clean(str);
			return true;
		}

		private static bool StringCleanC(string str)
		{
			StringExtensionC.Clean(str);
			return true;
		}
/*
		private static bool StringCleanD(string str)
		{
			StringExtensionD.Clean(str);
			return true;
		}
*/
	}


	public static class StringExtensionA
	{
		public static string Clean(string s)
		{
			return (new StringBuilder(s)).Replace("&", "and")
																	 .Replace(",", "")
			                             .Replace("  ", " ")
			                             .Replace(" ", "-")
			                             .Replace("'", "")
			                             .Replace(".", "")
			                             .Replace("eacute;", "é")
			                             .ToString().ToLower();
		}
	}

	public static class StringExtensionB
	{
		public static string Clean(string s)
		{
			StringBuilder sb = new StringBuilder(s);

			sb.Replace("&", "and");
			sb.Replace(",", "");
			sb.Replace("  ", " ");
			sb.Replace(" ", "-");
			sb.Replace("'", "");
			sb.Replace(".", "");
			sb.Replace("eacute;", "é");

			return sb.ToString().ToLower();
		}
	}

	public static class StringExtensionC
	{
		private static readonly Dictionary<string, string> Replacements = new Dictionary<string, string>()
			                                                                  {
				                                                                  {"&", "and"},
				                                                                  {",", ""},
				                                                                  {"  ", " "},
				                                                                  {" ", "-"},
				                                                                  {"'", ""},
				                                                                  {".", ""},
				                                                                  {"eacute;", "é"}
			                                                                  };

		/// LINQ Equivalent return Replacements.Keys.Aggregate(s, (current, toReplace) => current.Replace(toReplace, Replacements[toReplace]));
		public static string Clean(string s)
		{
			foreach (string toReplace in Replacements.Keys)
			{
				s = s.Replace(toReplace, Replacements[toReplace]);
			}
			return s;
		}
	}
/*
	public static class StringExtensionD
	{
		public static string Clean(string s)
		{
			Regex reg = new Regex(@"(\&)|(\,)|(\.)|(\W)|(eacute\;)", RegexOptions.IgnoreCase);
			return reg.Replace(s, match =>
				                      {
					                      switch (match.ToString())
					                      {
						                      case "&":
							                      return "and";
						                      case "eacute;":
							                      return "é";
					                      }
					                      return "";
				                      });
		}
	}
*/
}