Home
Manage Your Code
Snippet: BetterKnowAFramework (C#)
Title: BetterKnowAFramework Language: C#
Description: BetterKnowAFramework Views: 251
Author: Peter Parker Date Added: 4/28/2008
Copy Code  
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.Diagnostics;
5using System.Globalization;
6using System.IO;
7using System.IO.Compression;
8using System.Linq;
9using System.Linq.Expressions;
10using System.Reflection;
11using System.Security;
12using System.Security.Cryptography;
13using System.Security.Permissions;
14using System.Security.Policy;
15using System.Text;
16using System.Text.RegularExpressions;
17using System.Threading;
18using System.Xml;
19
20namespace Moserware.BetterKnowAFramework
21{
22    static class Program
23    {
24        static void Main(string[] args)
25        {
26            #region About me   ...            #endregion
32
33            // I gave this talk at Indy Code Camp on Saturday, April 26, 2008         

34            // The format was just stepping through this file by hitting F11

35            // in the debugger and discussing things as they came up.

36            #region   ...                         #endregion
49            #region Startup Things (a.k.a. "How did we get here?")               ...            #endregion
74            #region Beginner   ...            #endregion
81            #region Intermediate   ...            #endregion
91            #region A bit more challenging   ...            #endregion
115
116            // Questions?

117        }
118
119        private static void WarmupClasses()
120        {
121            #region System.IO.Path   ...            #endregion
133            #region System.Math (Show #293)   ...            #endregion
147            #region System.Console (Show #268)   ...            #endregion
161            #region Convert (Show #280)   ...            #endregion
169            #region System.Xml.XmlConvert   ...            #endregion
177            #region System.Environment (Show #269)   ...            #endregion
185            #region System.TimeSpan (Show #294)   ...            #endregion
190
191        }
192
193        private static void FunWithStrings()
194        {
195            #region System.Text.StringBuilder (Show #249)   ...                        #endregion
219            #region String formatting and IFormattable (Show #315)   ...            #endregion
241        }
242
243        private static void BoolVsEnumDebate()
244        {
245            // Which is easier to understand?

246
247            var exhibitA = string.Compare("Jeff", "jeff", true) == 0;
248            var exhibitB = string.Compare("Jeff", "jeff", StringComparison.CurrentCultureIgnoreCase) == 0;
249
250            // If you're designing public APIs, tend to prefer enums (e.g. StringComparison) over booleans.

251            // It just makes things easier to read.

252
253        }
254
255        private static void ILoveRegularExpressions()
256        {
257            // Here we're only going to show a few numbers. But just imagine

258            // If you had to process thousands or even millions.

259            string phoneNumbersOldFormat = "(800) 555-1212, (317) 222-1234, 765-4951234";
260            var newFormat = Regex.Replace(phoneNumbersOldFormat, @"[^\d,]*
261                                                                   (?<areaCode>\d{3})
262                                                                   \D*
263                                                                   (?<first3>\d{3})
264                                                                   \D*
265                                                                   (?<last4>\d{4})
266                                                                   [^,]*",
267                                                                   "${areaCode}.${first3}.${last4} ", RegexOptions.IgnorePatternWhitespace);
268
269            var isSsn = Regex.IsMatch("123-45-6789", @"\d{3}-\d{2}-\d{4}");
270            // many more possibilities

271            // see http://msdn2.microsoft.com/en-us/library/hs600312.aspx

272        }
273
274        private static void OverviewOfStreams()
275        {
276            // Streams are a generic concept in .net

277            // They're very swappable and connectable sort of like Legos.

278
279            // Let's create a stream that writes text, then compresses it,

280            // then encrypts it, then stores it in memory.

281                        
282            
283            var memory = new MemoryStream();
284            var secretKey = "My Secret Password!";
285            var salt = new byte[32];
286            var iv = new byte[16];
287            var passwordBytes = new Rfc2898DeriveBytes(secretKey, salt);
288            var encryptionAlgorithm = Aes.Create().CreateEncryptor(passwordBytes.GetBytes(32), iv);
289
290            var encryption = new CryptoStream(memory, encryptionAlgorithm, CryptoStreamMode.Write);
291
292            var compression = new GZipStream(encryption, CompressionMode.Compress);
293
294            var writer = new StreamWriter(compression);
295
296            // The pipeline/stream is

297            // writer => compression => encryption => memory

298            // Question: Why would this be a bad idea?

299            // writer => encryption => compression => memory

300
301            // As I mentioned in the talk and people in the audience got,

302            // you wouldn't want to do the latter because encrypted data

303            // should be random and won't compress much.

304
305            // Quick way to generate "Hello" repeated 500 times.

306            var input = string.Join(" ", Enumerable.Repeat("Hello", 500).ToArray());
307            var inputSize = input.Length;
308            writer.Write(input);
309            writer.Flush();
310            var outputBytes = memory.ToArray();
311
312            // Write the file from the MemoryStream to disk:

313
314            var temporaryFileName = Path.GetTempFileName();
315
316            using (var outputStream = File.OpenWrite(temporaryFileName))
317            {
318                memory.WriteTo(outputStream);
319            }
320
321            memory.Close();
322
323            // No time to cover IsolateStorageStream, but it's useful.

324
325        }
326
327        private static void AggregatesMakeMortHappy()
328        {            
329            // Aggregate Pattern 

330            // See "Framework Design Guidelines" pages 240-243

331
332            // Mort is someone who wants to get things done. 

333            // See: http://www.codinghorror.com/blog/archives/001004.html

334
335            // Mort likes 1 - 2 lines of code to get things done:

336            // var fileContents = File.ReadAllBytes(path)

337            // var wc = new System.Net.WebClient();

338            // var googlePage = wc.DownloadString("http://www.google.com/");            

339        }
340
341        private static void DabblingWithSecurity()
342        {
343            #region System.Security.Cryptography.RandomNumberGenerator (Show #244)   ...            #endregion
354            #region System.Security.Cryptography.ProtectedData   ...            #endregion
363        }
364
365
366        private static void InterestingInternalClasses()
367        {
368            // Didn't have time to cover this, but check out:

369            // see http://www.moserware.com/2008/01/borrowing-ideas-from-3-interesting.html

370            // System.Linq.Strings

371            // System.Linq.Error

372            // Microsoft.Contract.Contracts

373        }
374
375        private static void HowDoWeRelate()
376        {            
377            #region System.IComparable (Show #305)   ...            #endregion
390
391            // I didn't cover this but:

392            // If just want equality, override object.Equals(obj)

393            // Question: Why might you want to implement IEquatable?

394            // Answer: It helps value types not box

395
396            // By the way, if you overload Equals, you should overload GetHashCode()

397            // or else things that depend on hash codes (like Dictionary) will

398            // cause confusing results.

399
400        }
401
402        private static void DoesYourCodePassTheTurkeyTest()
403        {
404            // I gave a brief overview of this post:

405            // http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html

406
407            Thread.CurrentThread.CurrentCulture = new CultureInfo("tr-TR");
408            DateTime julyFourthA = DateTime.Parse("07/04/2008");
409            DateTime julyFourthB = DateTime.Parse("07/04/2008", DateTimeFormatInfo.InvariantInfo);
410
411            double fourPointFiveA = double.Parse("4.5");
412            double fourPointFiveB = double.Parse("4.5", NumberFormatInfo.InvariantInfo);
413
414            string fileUpperA = "file".ToUpper();
415            string fileUpperB = "file".ToUpperInvariant();
416            bool wacky = string.Equals(fileUpperA, fileUpperB);
417
418            bool sampleCompare = "File".Equals(fileUpperB, StringComparison.OrdinalIgnoreCase);
419        }
420
421        private static void SewingWithThreads()
422        {
423            #region Threading   ...                        #endregion
484        }
485
486        private static void EventsCanBeTricky()
487        {
488            var c = new SampleEventRaisingClass();
489            c.SomethingHappened += (s, e) => Console.WriteLine("Something Happened");
490            c.OnSomethingHappened();            
491        }
492
493        private static void BriefCoverageOfTracing()
494        {
495            #region Shows #333 and #334   ...            #endregion
505
506        }
507
508        private static void UnderstandingHowLinqIsImplemented()
509        {
510            // A look under the covers of how LINQ is implemented:

511
512            var numbers1To50 = Enumerable.Range(1, 50);
513
514            // This LINQ statement in the SQL-esque syntax:

515            var evenNumbersSquared = from n in numbers1To50 where (n % 2 == 0) select n * n;
516
517            // is identical to this:

518            var alternately = numbers1To50.Where(n => n % 2 == 0).Select(n => n * n);
519
520            // but could also be rewritten this way (note that I define GetEvens and GetSquares below)

521            var orHowAbout = numbers1To50.GetEvens().GetSquares();
522
523            // You can do this manually too:

524            Func<int, bool> isEven = n => (n % 2) == 0;
525
526            // or using the uglier C# 2 syntax:

527            Func<int, int> squarer = delegate(int n)
528                                     {
529                                         return n * n;
530                                     };
531
532            var yetAnother = numbers1To50.Where(isEven).Select(squarer);
533
534            // More advanced uses of LINQ methods:

535
536            Func<int, int> factorial = n => Enumerable.Range(1, n).Aggregate(1, (a, i) => a * i);
537            var fact5 = factorial(5);
538
539            var sum1To10 = Enumerable.Range(1, 10).Sum();
540
541            // Express yourself..

542            // See: http://www.codeproject.com/KB/cs/explore_lamda_exp.aspx

543
544            Expression<Func<int, int>> square = x => x * x;
545            BinaryExpression squareplus2 = Expression.Add(square.Body,
546                Expression.Constant(2));
547            Expression<Func<int, int>> expr = Expression.Lambda<Func<int, int>>(squareplus2,
548                square.Parameters);
549
550            Func<int, int> compile = expr.Compile();
551            var result = compile(5);
552
553            // LINQ works with both Func's and Expression's

554            // Expressions are used when you want to understand more of the intent

555            // of what the programmer wants to do (typically multiple operations)

556
557            // Show #319 - IQueryable and IQueryProvider

558
559            // The best way to learn for me was to listen straight from Anders:

560            // http://langnetsymposium.com/talks.asp (click on Anders' talk)

561
562        }
563
564        private static IEnumerable<int> GetEvens(this IEnumerable<int> collection)
565        {
566            foreach (int n in collection)
567            {
568                if (n % 2 == 0)
569                {
570                    yield return n;
571                }
572            }
573        }
574
575        private static IEnumerable<int> GetSquares(this IEnumerable<int> collection)
576        {
577            foreach (int n in collection)
578            {
579                yield return n * n;
580            }
581        }
582
583        private static void PeeringIntoIDisposable()
584        {
585            #region IDisposable (Show #287)   ...            #endregion
618        }
619
620        private static void ExploringSystemCollectionsGeneric()
621        {
622            // Arrays are used internally for collections. 

623            // You can usually forget this, but sometimes it's good to know

624            #region System.Collections.Generic   ...                        #endregion
736        }
737        #region AppDomain Sandbox   ...        #endregion
828    }
829
830    internal class MyNumber : IFormattable, IComparable
831    {
832        private readonly int m_Number;
833
834        public MyNumber(int number)
835        {
836            m_Number = number;
837        }
838        #region IFormattable Members   ...        #endregion
853        #region IComparable Members   ...        #endregion
861    }
862
863    class RomanNumeral
864    {
865        static private Dictionary<char, int> m_LetterToValue = new Dictionary<char, int>();
866        static private char[] m_MostToLeast = new char[] { 'M', 'D', 'C', 'L', 'X', 'V', 'I' };
867
868        static RomanNumeral()
869        {
870            m_LetterToValue['I'] = 1;
871            m_LetterToValue['V'] = 5;
872            m_LetterToValue['X'] = 10;
873            m_LetterToValue['L'] = 50;
874            m_LetterToValue['C'] = 100;
875            m_LetterToValue['D'] = 500;
876            m_LetterToValue['M'] = 1000;
877
878        }
879
880        public static string Encode(int number)
881        {
882            var sb = new StringBuilder();
883            int remainder = number;
884
885            while (remainder > 0)
886            {
887                foreach (char c in m_MostToLeast)
888                {
889                    if ((remainder - m_LetterToValue[c]) >= 0)
890                    {
891                        sb.Append(c);
892                        remainder -= m_LetterToValue[c];
893                        break;
894                    }
895                }
896            }
897
898            // Now to optimizations

899            sb.Replace("VIIII", "IX");
900            sb.Replace("IIII", "IV");
901            sb.Replace("XXXX", "XL");
902            sb.Replace("LXXXX", "XC");
903            sb.Replace("CCCC", "CD");
904            sb.Replace("DCD", "CM");
905            sb.Replace("LXL", "XC");
906            sb.Replace("DCCCC", "CM");
907
908            return sb.ToString();
909        }
910    }
911
912    class SampleEventRaisingClass
913    {
914        public event EventHandler<EventArgs> SomethingHappened;
915
916        public void OnSomethingHappened()
917        {
918            // how many things can you count wrong in this one line of code?

919            SomethingHappened(this, EventArgs.Empty);
920
921            // HINT:

922
923            // 1. It shouldn't be public

924            // 2. should check for null:

925            //    if (SomethingHappened != null)

926            //    {

927            //       SomethingHappened(this, EventArgs.Empty);

928            //    }

929            // 3. But even that is wrong, there exists a possibility that 

930            //    SomethingHappened could become null after you checked it:

931            //    var handler = SomethingHappened;

932            //    if (handler != null)

933            //    {

934            //        handler(this, EventArgs.Empty);

935            //    }

936
937            // What happens if your handlers throw an exception? What happens

938            // if your handler should be called on the UI thread, etc...

939
940            // Lots of things to think about, that's why you should really look

941            // at Juval's EventsHelper class:

942            // https://opensvn.csie.org/traccgi/BuckRogers/browser/trunk/Networking/EventsHelper.cs

943
944            // and use that everywhere instead of manually doing all these checks

945            // each time.

946
947        }
948    }
949}
Notes
http://www.moserware.com/