diff options
| author | Suzane Sant Ana <tetestonaldo@gmail.com> | 2017-12-31 14:27:06 -0200 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-12-31 14:27:06 -0200 | 
| commit | 42f9329bb3a028d374d6397991ac48b44064741e (patch) | |
| tree | 1e75e2b3e122aeb863e3ffa037f6f64c4027fbf8 /csharp.html.markdown | |
| parent | e6b77595f2669d66ac7be43c6e6083cbff80a9a7 (diff) | |
| parent | 70a36c9bd970b928adde06afb2bd69f6ba8e5d5c (diff) | |
Merge pull request #1 from adambard/master
update
Diffstat (limited to 'csharp.html.markdown')
| -rw-r--r-- | csharp.html.markdown | 665 | 
1 files changed, 582 insertions, 83 deletions
| diff --git a/csharp.html.markdown b/csharp.html.markdown index 47dd9683..f27adf18 100644 --- a/csharp.html.markdown +++ b/csharp.html.markdown @@ -5,6 +5,10 @@ contributors:      - ["Max Yankov", "https://github.com/golergka"]      - ["Melvyn Laïly", "http://x2a.yt"]      - ["Shaun McCarthy", "http://www.shaunmccarthy.com"] +    - ["Wouter Van Schandevijl", "http://github.com/laoujin"] +    - ["Jo Pearce", "http://github.com/jdpearce"] +    - ["Chris Zimmerman", "https://github.com/chriszimmerman"] +    - ["Shawn McGuire", "https://github.com/bigbash"]  filename: LearnCSharp.cs  --- @@ -18,29 +22,38 @@ C# is an elegant and type-safe object-oriented language that enables developers  Multi-line comments look like this  */  /// <summary> -/// This is an XML documentation comment +/// This is an XML documentation comment which can be used to generate external +/// documentation or provide context help within an IDE  /// </summary> +/// <param name="firstParam">This is some parameter documentation for firstParam</param> +/// <returns>Information on the returned value of a function</returns> +//public void MethodOrClassOrOtherWithParsableHelp(string firstParam) {} -// Specify namespaces application will be using +// Specify the namespaces this source code will be using +// The namespaces below are all part of the standard .NET Framework Class Library  using System;  using System.Collections.Generic; -using System.Data.Entity;  using System.Dynamic;  using System.Linq; -using System.Linq.Expressions;  using System.Net;  using System.Threading.Tasks;  using System.IO; -// defines scope to organize code into "packages" -namespace Learning +// But this one is not: +using System.Data.Entity; +// In order to be able to use it, you need to add a dll reference +// This can be done with the NuGet package manager: `Install-Package EntityFramework` + +// Namespaces define scope to organize code into "packages" or "modules" +// Using this code from another source file: using Learning.CSharp; +namespace Learning.CSharp  { -    // Each .cs file should at least contain a class with the same name as the file -    // you're allowed to do otherwise, but shouldn't for sanity. +    // Each .cs file should at least contain a class with the same name as the file. +    // You're allowed to do otherwise, but shouldn't for sanity.      public class LearnCSharp      {          // BASIC SYNTAX - skip to INTERESTING FEATURES if you have used Java or C++ before -        public static void Syntax()  +        public static void Syntax()          {              // Use Console.WriteLine to print lines              Console.WriteLine("Hello World"); @@ -119,13 +132,19 @@ namespace Learning              DateTime fooDate = DateTime.Now;              Console.WriteLine(fooDate.ToString("hh:mm, dd MMM yyyy")); +            // Verbatim String +            // You can use the @ symbol before a string literal to escape all characters in the string +            string path = "C:\\Users\\User\\Desktop"; +            string verbatimPath = @"C:\Users\User\Desktop"; +            Console.WriteLine(path == verbatimPath);  // => true +              // You can split a string over two lines with the @ symbol. To escape " use ""              string bazString = @"Here's some stuff  on a new line! ""Wow!"", the masses cried";              // Use const or read-only to make a variable immutable              // const values are calculated at compile time -            const int HOURS_I_WORK_PER_WEEK = 9001; +            const int HoursWorkPerWeek = 9001;              ///////////////////////////////////////////////////              // Data Structures @@ -151,7 +170,7 @@ on a new line! ""Wow!"", the masses cried";              // List<datatype> <var name> = new List<datatype>();              List<int> intList = new List<int>();              List<string> stringList = new List<string>(); -            List<int> z = new List<int> { 9000, 1000, 1337 }; // intialize +            List<int> z = new List<int> { 9000, 1000, 1337 }; // initialize              // The <> are for generics - Check out the cool stuff section              // Lists don't default to a value; @@ -200,10 +219,10 @@ on a new line! ""Wow!"", the masses cried";              // Incrementations              int i = 0;              Console.WriteLine("\n->Inc/Dec-rementation"); -            Console.WriteLine(i++); //i = 1. Post-Incrementation -            Console.WriteLine(++i); //i = 2. Pre-Incrementation -            Console.WriteLine(i--); //i = 1. Post-Decrementation -            Console.WriteLine(--i); //i = 0. Pre-Decrementation +            Console.WriteLine(i++); //Prints "0", i = 1. Post-Incrementation +            Console.WriteLine(++i); //Prints "2", i = 2. Pre-Incrementation +            Console.WriteLine(i--); //Prints "2", i = 1. Post-Decrementation +            Console.WriteLine(--i); //Prints "0", i = 0. Pre-Decrementation              ///////////////////////////////////////              // Control Structures @@ -228,7 +247,8 @@ on a new line! ""Wow!"", the masses cried";              // Ternary operators              // A simple if/else can be written as follows              // <condition> ? <true> : <false> -            string isTrue = (true) ? "True" : "False"; +            int toCompare = 17; +            string isTrue = toCompare == 17 ? "True" : "False";              // While loop              int fooWhile = 0; @@ -242,8 +262,15 @@ on a new line! ""Wow!"", the masses cried";              int fooDoWhile = 0;              do              { -                //Iterated 100 times, fooDoWhile 0->99 +                // Start iteration 100 times, fooDoWhile 0->99 +                if (false) +                    continue; // skip the current iteration +                  fooDoWhile++; + +                if (fooDoWhile == 50) +                    break; // breaks from the loop completely +              } while (fooDoWhile < 100);              //for loop structure => for(<start_statement>; <conditional>; <step>) @@ -301,7 +328,7 @@ on a new line! ""Wow!"", the masses cried";              // Converting data              // Convert String To Integer -            // this will throw an Exception on failure +            // this will throw a FormatException on failure              int.Parse("123");//returns an integer version of "123"              // try parse will default to type default on failure @@ -315,6 +342,11 @@ on a new line! ""Wow!"", the masses cried";              Convert.ToString(123);              // or              tryInt.ToString(); + +            // Casting +            // Cast decimal 15 to a int +            // and then implicitly cast to long +            long x = (int) 15M;          }          /////////////////////////////////////// @@ -350,11 +382,11 @@ on a new line! ""Wow!"", the masses cried";          //          // INTERESTING FEATURES          // -         +          // DEFAULT METHOD SIGNATURES          public // Visibility -        static // Allows for direct call on class without object  +        static // Allows for direct call on class without object          int // Return Type,          MethodSignatures(              int maxCount, // First variable, expects an int @@ -362,21 +394,26 @@ on a new line! ""Wow!"", the masses cried";              int another = 3,              params string[] otherParams // captures all other parameters passed to method          ) -        {  +        {              return -1;          }          // Methods can have the same name, as long as the signature is unique -        public static void MethodSignatures(string maxCount) +        // A method that differs only in return type is not unique +        public static void MethodSignatures( +            ref int maxCount, // Pass by reference +            out int count)          { +            //the argument passed in as 'count' will hold the value of 15 outside of this function +            count = 15; // out param must be assigned before control leaves the method          }          // GENERICS          // The classes for TKey and TValue is specified by the user calling this function.          // This method emulates the SetDefault of Python          public static TValue SetDefault<TKey, TValue>( -            IDictionary<TKey, TValue> dictionary,  -            TKey key,  +            IDictionary<TKey, TValue> dictionary, +            TKey key,              TValue defaultItem)          {              TValue result; @@ -385,7 +422,7 @@ on a new line! ""Wow!"", the masses cried";              return result;          } -        // You can narrow down the objects that are passed in  +        // You can narrow down the objects that are passed in          public static void IterateAndPrint<T>(T toPrint) where T: IEnumerable<int>          {              // We can iterate, since T is a IEnumerable @@ -394,11 +431,51 @@ on a new line! ""Wow!"", the masses cried";                  Console.WriteLine(item.ToString());          } +        // YIELD +        // Usage of the "yield" keyword indicates that the method it appears in is an Iterator +        // (this means you can use it in a foreach loop) +        public static IEnumerable<int> YieldCounter(int limit = 10) +        { +            for (var i = 0; i < limit; i++) +                yield return i; +        } + +        // which you would call like this : +        public static void PrintYieldCounterToConsole() +        { +            foreach (var counter in YieldCounter()) +                Console.WriteLine(counter); +        } + +        // you can use more than one "yield return" in a method +        public static IEnumerable<int> ManyYieldCounter() +        { +            yield return 0; +            yield return 1; +            yield return 2; +            yield return 3; +        } + +        // you can also use "yield break" to stop the Iterator +        // this method would only return half of the values from 0 to limit. +        public static IEnumerable<int> YieldCounterWithBreak(int limit = 10) +        { +            for (var i = 0; i < limit; i++) +            { +                if (i > limit/2) yield break; +                yield return i; +            } +        } +          public static void OtherInterestingFeatures()          {              // OPTIONAL PARAMETERS              MethodSignatures(3, 1, 3, "Some", "Extra", "Strings"); -            MethodSignatures(3, another: 3); // explicity set a parameter, skipping optional ones +            MethodSignatures(3, another: 3); // explicitly set a parameter, skipping optional ones + +            // BY REF AND OUT PARAMETERS +            int maxCount = 0, count; // ref params must have value +            MethodSignatures(ref maxCount, out count);              // EXTENSION METHODS              int i = 3; @@ -415,19 +492,22 @@ on a new line! ""Wow!"", the masses cried";              // in case variable is null              int notNullable = nullable ?? 0; // 0 +            // ?. is an operator for null-propagation - a shorthand way of checking for null +            nullable?.Print(); // Use the Print() extension method if nullable isn't null +              // IMPLICITLY TYPED VARIABLES - you can let the compiler work out what the type is:              var magic = "magic is a string, at compile time, so you still get type safety";              // magic = 9; will not work as magic is a string, not an int              // GENERICS              // -            var phonebook = new Dictionary<string, string>() {  +            var phonebook = new Dictionary<string, string>() {                  {"Sarah", "212 555 5555"} // Add some entries to the phone book              };              // Calling SETDEFAULT defined as a generic above              Console.WriteLine(SetDefault<string,string>(phonebook, "Shaun", "No Phone")); // No Phone -            // nb, you don't need to specify the TKey and TValue since they can be  +            // nb, you don't need to specify the TKey and TValue since they can be              // derived implicitly              Console.WriteLine(SetDefault(phonebook, "Sarah", "No Phone")); // 212 555 5555 @@ -435,41 +515,60 @@ on a new line! ""Wow!"", the masses cried";              Func<int, int> square = (x) => x * x; // Last T item is the return value              Console.WriteLine(square(3)); // 9 +            // ERROR HANDLING - coping with an uncertain world +            try +            { +                var funBike = PennyFarthing.CreateWithGears(6); + +                // will no longer execute because CreateWithGears throws an exception +                string some = ""; +                if (true) some = null; +                some.ToLower(); // throws a NullReferenceException +            } +            catch (NotSupportedException) +            { +                Console.WriteLine("Not so much fun now!"); +            } +            catch (Exception ex) // catch all other exceptions +            { +                throw new ApplicationException("It hit the fan", ex); +                // throw; // A rethrow that preserves the callstack +            } +            // catch { } // catch-all without capturing the Exception +            finally +            { +                // executes after try or catch +            } +              // DISPOSABLE RESOURCES MANAGEMENT - let you handle unmanaged resources easily.              // Most of objects that access unmanaged resources (file handle, device contexts, etc.) -            // implement the IDisposable interface. The using statement takes care of  +            // implement the IDisposable interface. The using statement takes care of              // cleaning those IDisposable objects for you.              using (StreamWriter writer = new StreamWriter("log.txt"))              {                  writer.WriteLine("Nothing suspicious here");                  // At the end of scope, resources will be released.                  // Even if an exception is thrown. -            }  +            }              // PARALLEL FRAMEWORK              // http://blogs.msdn.com/b/csharpfaq/archive/2010/06/01/parallel-programming-in-net-framework-4-getting-started.aspx -            var websites = new string[] {  -                "http://www.google.com", "http://www.reddit.com",  -                "http://www.shaunmccarthy.com" -            }; -            var responses = new Dictionary<string, string>(); -             -            // Will spin up separate threads for each request, and join on them -            // before going to the next step! -            Parallel.ForEach(websites,  -                new ParallelOptions() {MaxDegreeOfParallelism = 3}, // max of 3 threads -                website => -            { -                // Do something that takes a long time on the file -                using (var r = WebRequest.Create(new Uri(website)).GetResponse()) + +            var words = new List<string> {"dog", "cat", "horse", "pony"}; + +            Parallel.ForEach(words, +                new ParallelOptions() { MaxDegreeOfParallelism = 4 }, +                word =>                  { -                    responses[website] = r.ContentType; +                    Console.WriteLine(word);                  } -            }); +            ); -            // This won't happen till after all requests have been completed -            foreach (var key in responses.Keys) -                Console.WriteLine("{0}:{1}", key, responses[key]); +            //Running this will produce different outputs +            //since each thread finishes at different times. +            //Some example outputs are: +            //cat dog horse pony +            //dog horse pony cat              // DYNAMIC OBJECTS (great for working with other languages)              dynamic student = new ExpandoObject(); @@ -480,7 +579,7 @@ on a new line! ""Wow!"", the masses cried";                  (introduceTo) => string.Format("Hey {0}, this is {1}", student.FirstName, introduceTo));              Console.WriteLine(student.Introduce("Beth")); -            // IQUERYABLE<T> - almost all collections implement this, which gives you a lot of  +            // IQUERYABLE<T> - almost all collections implement this, which gives you a lot of              // very useful Map / Filter / Reduce style methods              var bikes = new List<Bicycle>();              bikes.Sort(); // Sorts the array @@ -500,10 +599,10 @@ on a new line! ""Wow!"", the masses cried";                  Console.WriteLine(bikeSummary.Name);              // ASPARALLEL -            // And this is where things get wicked - combines linq and parallel operations +            // And this is where things get wicked - combine linq and parallel operations              var threeWheelers = bikes.AsParallel().Where(b => b.Wheels == 3).Select(b => b.Name); -            // this will happen in parallel! Threads will automagically be spun up and the  -            // results divvied amongst them! Amazing for large datasets when you have lots of  +            // this will happen in parallel! Threads will automagically be spun up and the +            // results divvied amongst them! Amazing for large datasets when you have lots of              // cores              // LINQ - maps a store to IQueryable<T> objects, with delayed execution @@ -520,10 +619,10 @@ on a new line! ""Wow!"", the masses cried";                  .ThenBy(b => b.Name)                  .Select(b => b.Name); // still no query run -            // Now the query runs, but opens a reader, so only populates are you iterate through -            foreach (string bike in query)  +            // Now the query runs, but opens a reader, so only populates as you iterate through +            foreach (string bike in query)                  Console.WriteLine(result); -             +          } @@ -534,13 +633,61 @@ on a new line! ""Wow!"", the masses cried";      public static class Extensions      { -        // EXTENSION FUNCTIONS +        // EXTENSION METHODS          public static void Print(this object obj)          {              Console.WriteLine(obj.ToString());          }      } + +    // DELEGATES AND EVENTS +    public class DelegateTest +    { +        public static int count = 0; +        public static int Increment() +        { +            // increment count then return it +            return ++count; +        } + +        // A delegate is a reference to a method +        // To reference the Increment method, +        // first declare a delegate with the same signature +        // ie. takes no arguments and returns an int +        public delegate int IncrementDelegate(); + +        // An event can also be used to trigger delegates +        // Create an event with the delegate type +        public static event IncrementDelegate MyEvent; + +        static void Main(string[] args) +        { +            // Refer to the Increment method by instantiating the delegate +            // and passing the method itself in as an argument +            IncrementDelegate inc = new IncrementDelegate(Increment); +            Console.WriteLine(inc());  // => 1 + +            // Delegates can be composed with the + operator +            IncrementDelegate composedInc = inc; +            composedInc += inc; +            composedInc += inc; + +            // composedInc will run Increment 3 times +            Console.WriteLine(composedInc());  // => 4 + + +            // Subscribe to the event with the delegate +            MyEvent += new IncrementDelegate(Increment); +            MyEvent += new IncrementDelegate(Increment); + +            // Trigger the event +            // ie. run all delegates subscribed to this event +            Console.WriteLine(MyEvent());  // => 6 +        } +    } + +      // Class Declaration Syntax:      // <public/private/protected/internal> class <class name>{      //    //data fields, constructors, functions all inside. @@ -556,7 +703,7 @@ on a new line! ""Wow!"", the masses cried";              {                  return _cadence;              } -            set // set - define a method to set a proprety +            set // set - define a method to set a property              {                  _cadence = value; // Value is the value passed in to the setter              } @@ -575,9 +722,13 @@ on a new line! ""Wow!"", the masses cried";              private set; // You can set modifiers on the get/set methods          } -        int _speed; // Everything is private by default: Only accessible from within this class.  +        int _speed; // Everything is private by default: Only accessible from within this class.                      // can also use keyword private          public string Name { get; set; } +         +        // Properties also have a special syntax for when you want a readonly property +        // that simply returns the result of an expression +        public string LongName => Name + " " + _speed + " speed";           // Enum is a value type that consists of a set of named constants          // It is really just mapping a name to a value (an int, unless specified otherwise). @@ -595,10 +746,29 @@ on a new line! ""Wow!"", the masses cried";          public BikeBrand Brand; // After declaring an enum type, we can declare the field of this type -        // Static members belong to the type itself rather then specific object. +        // Decorate an enum with the FlagsAttribute to indicate that multiple values can be switched on +        // Any class derived from Attribute can be used to decorate types, methods, parameters etc +        // Bitwise operators & and | can be used to perform and/or operations + +        [Flags] +        public enum BikeAccessories +        { +            None = 0, +            Bell = 1, +            MudGuards = 2, // need to set the values manually! +            Racks = 4, +            Lights = 8, +            FullPackage = Bell | MudGuards | Racks | Lights +        } + +        // Usage: aBike.Accessories.HasFlag(Bicycle.BikeAccessories.Bell) +        // Before .NET 4: (aBike.Accessories & Bicycle.BikeAccessories.Bell) == Bicycle.BikeAccessories.Bell +        public BikeAccessories Accessories { get; set; } + +        // Static members belong to the type itself rather than specific object.          // You can access them without a reference to any object:          // Console.WriteLine("Bicycles created: " + Bicycle.bicyclesCreated); -        static public int BicyclesCreated = 0; +        public static int BicyclesCreated { get; set; }          // readonly values are set at run time          // they can only be assigned upon declaration or in a constructor @@ -606,7 +776,7 @@ on a new line! ""Wow!"", the masses cried";          // Constructors are a way of creating classes          // This is a default constructor -        public Bicycle()  +        public Bicycle()          {              this.Gear = 1; // you can access members of the object with the keyword this              Cadence = 50;  // but you don't always need it @@ -618,13 +788,13 @@ on a new line! ""Wow!"", the masses cried";          // This is a specified constructor (it contains arguments)          public Bicycle(int startCadence, int startSpeed, int startGear, -                       string name, bool hasCardsInSpokes, BikeBrand brand)  +                       string name, bool hasCardsInSpokes, BikeBrand brand)              : base() // calls base first          { -            Gear = startGear;  +            Gear = startGear;              Cadence = startCadence;              _speed = startSpeed; -            Name = name;  +            Name = name;              _hasCardsInSpokes = hasCardsInSpokes;              Brand = brand;          } @@ -680,9 +850,9 @@ on a new line! ""Wow!"", the masses cried";          // It's also possible to define custom Indexers on objects.          // All though this is not entirely useful in this example, you -        // could do bicycle[0] which yields "chris" to get the first passenger or +        // could do bicycle[0] which returns "chris" to get the first passenger or          // bicycle[1] = "lisa" to set the passenger. (of this apparent quattrocycle) -        private string[] passengers = { "chris", "phil", "darren", "regina" } +        private string[] passengers = { "chris", "phil", "darren", "regina" };          public string this[int i]          { @@ -691,7 +861,7 @@ on a new line! ""Wow!"", the masses cried";              }              set { -                return passengers[i] = value; +                passengers[i] = value;              }          } @@ -708,7 +878,7 @@ on a new line! ""Wow!"", the masses cried";          }          // Methods can also be static. It can be useful for helper methods -        public static bool DidWeCreateEnoughBycles() +        public static bool DidWeCreateEnoughBicycles()          {              // Within a static method, we only can reference static class members              return BicyclesCreated > 9000; @@ -737,10 +907,17 @@ on a new line! ""Wow!"", the masses cried";              }              set              { -                throw new ArgumentException("You can't change gears on a PennyFarthing"); +                throw new InvalidOperationException("You can't change gears on a PennyFarthing");              }          } +        public static PennyFarthing CreateWithGears(int gears) +        { +            var penny = new PennyFarthing(1, 1); +            penny.Gear = gears; // Oops, can't do this! +            return penny; +        } +          public override string Info()          {              string result = "PennyFarthing bicycle "; @@ -760,7 +937,8 @@ on a new line! ""Wow!"", the masses cried";          bool Broken { get; } // interfaces can contain properties as well as methods & events      } -    // Class can inherit only one other class, but can implement any amount of interfaces +    // Classes can inherit only one other class, but can implement any amount of interfaces, +    // however the base class name must be the first in the list and all interfaces follow      class MountainBike : Bicycle, IJumpable, IBreakable      {          int damage = 0; @@ -780,11 +958,11 @@ on a new line! ""Wow!"", the masses cried";      }      /// <summary> -    /// Used to connect to DB for LinqToSql example.  +    /// Used to connect to DB for LinqToSql example.      /// EntityFramework Code First is awesome (similar to Ruby's ActiveRecord, but bidirectional)      /// http://msdn.microsoft.com/en-us/data/jj193542.aspx      /// </summary> -    public class BikeRepository : DbSet +    public class BikeRepository : DbContext      {          public BikeRepository()              : base() @@ -793,18 +971,342 @@ on a new line! ""Wow!"", the masses cried";          public DbSet<Bicycle> Bikes { get; set; }      } + +    // Classes can be split across multiple .cs files +    // A1.cs +    public partial class A +    { +        public static void A1() +        { +            Console.WriteLine("Method A1 in class A"); +        } +    } + +    // A2.cs +    public partial class A +    { +        public static void A2() +        { +            Console.WriteLine("Method A2 in class A"); +        } +    } + +    // Program using the partial class "A" +    public class Program +    { +        static void Main() +        { +            A.A1(); +            A.A2(); +        } +    } + +    // String interpolation by prefixing the string with $ +    // and wrapping the expression you want to interpolate with { braces } +    // You can also combine both interpolated and verbatim strings with $@ +    public class Rectangle +    { +        public int Length { get; set; } +        public int Width { get; set; } +    } + +    class Program +    { +        static void Main(string[] args) +        { +            Rectangle rect = new Rectangle { Length = 5, Width = 3 }; +            Console.WriteLine($"The length is {rect.Length} and the width is {rect.Width}"); + +            string username = "User"; +            Console.WriteLine($@"C:\Users\{username}\Desktop"); +        } +    } + +    // New C# 6 features +    class GlassBall : IJumpable, IBreakable +    { +        // Autoproperty initializers +        public int Damage { get; private set; } = 0; + +        // Autoproperty initializers on getter-only properties +        public string Name { get; } = "Glass ball"; + +        // Getter-only autoproperty that is initialized in constructor +        public string GenieName { get; } + +        public GlassBall(string genieName = null) +        { +            GenieName = genieName; +        } + +        public void Jump(int meters) +        { +            if (meters < 0) +                // New nameof() expression; compiler will check that the identifier exists +                // nameof(x) == "x" +                // Prevents e.g. parameter names changing but not updated in error messages +                throw new ArgumentException("Cannot jump negative amount!", nameof(meters)); + +            Damage += meters; +        } + +        // Expression-bodied properties ... +        public bool Broken +            => Damage > 100; + +        // ... and methods +        public override string ToString() +            // Interpolated string +            => $"{Name}. Damage taken: {Damage}"; + +        public string SummonGenie() +            // Null-conditional operators +            // x?.y will return null immediately if x is null; y is not evaluated +            => GenieName?.ToUpper(); +    } + +    static class MagicService +    { +        private static bool LogException(Exception ex) +        { +            /* log exception somewhere */ +            return false; +        } + +        public static bool CastSpell(string spell) +        { +            try +            { +                // Pretend we call API here +                throw new MagicServiceException("Spell failed", 42); + +                // Spell succeeded +                return true; +            } +            // Only catch if Code is 42 i.e. spell failed +            catch(MagicServiceException ex) when (ex.Code == 42) +            { +                // Spell failed +                return false; +            } +            // Other exceptions, or MagicServiceException where Code is not 42  +            catch(Exception ex) when (LogException(ex)) +            { +                // Execution never reaches this block +                // The stack is not unwound +            } +            return false; +            // Note that catching a MagicServiceException and rethrowing if Code +            // is not 42 or 117 is different, as then the final catch-all block +            // will not catch the rethrown exception +        } +    } + +    public class MagicServiceException : Exception +    { +        public int Code { get; } + +        public MagicServiceException(string message, int code) : base(message) +        { +            Code = code; +        } +    } + +    public static class PragmaWarning { +        // Obsolete attribute +        [Obsolete("Use NewMethod instead", false)] +        public static void ObsoleteMethod() +        { +            /* obsolete code */ +        } + +        public static void NewMethod() +        { +            /* new code */ +        } + +        public static void Main() +        { +            ObsoleteMethod(); // CS0618: 'ObsoleteMethod is obsolete: Use NewMethod instead' +#pragma warning disable CS0618 +            ObsoleteMethod(); // no warning +#pragma warning restore CS0618 +            ObsoleteMethod(); // CS0618: 'ObsoleteMethod is obsolete: Use NewMethod instead' +        } +    }  } // End Namespace + +using System; +// C# 6, static using +using static System.Math; + +namespace Learning.More.CSharp +{ +    class StaticUsing +    { +        static void Main() +        { +            // Without a static using statement.. +            Console.WriteLine("The square root of 4 is {}.", Math.Sqrt(4)); +            // With one +            Console.WriteLine("The square root of 4 is {}.", Sqrt(4)); +        } +    } +} + +//New C# 7 Feature +//Install Microsoft.Net.Compilers Latest from Nuget +//Install System.ValueTuple Latest from Nuget +using System; +namespace Csharp7 +{ +    // TUPLES, DECONSTRUCTION AND DISCARDS +    class TuplesTest +    { +        public (string, string) GetName() +        { +            // Fields in tuples are by default named Item1, Item2... +            var names1 = ("Peter", "Parker"); +            Console.WriteLine(names1.Item2);  // => Parker + +            // Fields can instead be explicitly named +            // Type 1 Declaration +            (string FirstName, string LastName) names2 = ("Peter", "Parker"); + +            // Type 2 Declaration +            var names3 = (First:"Peter", Last:"Parker"); + +            Console.WriteLine(names2.FirstName);  // => Peter +            Console.WriteLine(names3.Last);  // => Parker + +            return names3; +        } + +        public string GetLastName() { +            var fullName = GetName(); + +            // Tuples can be deconstructed +            (string firstName, string lastName) = fullName; + +            // Fields in a deconstructed tuple can be discarded by using _ +            var (_, last) = fullName; +            return last; +        } + +        // Any type can be deconstructed in the same way by +        // specifying a Deconstruct method +        public int randomNumber = 4; +        public int anotherRandomNumber = 10; + +        public void Deconstruct(out int randomNumber, out int anotherRandomNumber) +        { +            randomNumber = this.randomNumber; +            anotherRandomNumber = this.anotherRandomNumber; +        } + +        static void Main(string[] args) +        { +            var tt = new TuplesTest(); +            (int num1, int num2) = tt; +            Console.WriteLine($"num1: {num1}, num2: {num2}");  // => num1: 4, num2: 10 + +            Console.WriteLine(tt.GetLastName()); +        } +    } +     +    // PATTERN MATCHING +    class PatternMatchingTest +    { +        public static (string, int)? CreateLogMessage(object data) +        { +            switch(data) +            { +                // Additional filtering using when +                case System.Net.Http.HttpRequestException h when h.Message.Contains("404"): +                    return (h.Message, 404); +                case System.Net.Http.HttpRequestException h when h.Message.Contains("400"): +                    return (h.Message, 400); +                case Exception e: +                    return (e.Message, 500); +                case string s: +                    return (s, s.Contains("Error") ? 500 : 200); +                case null: +                    return null; +                default: +                    return (data.ToString(), 500); +            } +        } +    } + +    // REFERENCE LOCALS +    // Allow you to return a reference to an object instead of just its value +    class RefLocalsTest +    { +        // note ref in return +        public static ref string FindItem(string[] arr, string el) +        { +            for(int i=0; i<arr.Length; i++) +            { +                if(arr[i] == el) { +                    // return the reference +                    return ref arr[i]; +                } +            } +            throw new Exception("Item not found"); +        } + +        public static void SomeMethod() +        { +            string[] arr = {"this", "is", "an", "array"}; + +            // note refs everywhere +            ref string item = ref FindItem(arr, "array"); +            item = "apple"; +            Console.WriteLine(arr[3]);  // => apple +        } +    } + +    // LOCAL FUNCTIONS +    class LocalFunctionTest +    { +        private static int _id = 0; +        public int id; +        public LocalFunctionTest() +        { +            id = generateId(); + +            // This local function can only be accessed in this scope +            int generateId() +            { +                return _id++; +            } +        } + +        public static void AnotherMethod() +        { +            var lf1 = new LocalFunctionTest(); +            var lf2 = new LocalFunctionTest(); +            Console.WriteLine($"{lf1.id}, {lf2.id}");  // => 0, 1 + +            int id = generateId(); +            // error CS0103: The name 'generateId' does not exist in the current context +        } +    } +} +  ```  ## Topics Not Covered - * Flags   * Attributes - * Static properties - * Exceptions, Abstraction - * ASP.NET (Web Forms/MVC/WebMatrix) - * Winforms - * Windows Presentation Foundation (WPF) + * async/await + * Web Development + 	* ASP.NET MVC & WebApi (new) + 	* ASP.NET Web Forms (old) + 	* WebMatrix (tool) + * Desktop Development + 	* Windows Presentation Foundation (WPF) (new) + 	* Winforms (old)  ## Further Reading @@ -817,7 +1319,4 @@ on a new line! ""Wow!"", the masses cried";   * [ASP.NET Web Matrix Tutorials](http://www.asp.net/web-pages/tutorials)   * [ASP.NET Web Forms Tutorials](http://www.asp.net/web-forms/tutorials)   * [Windows Forms Programming in C#](http://www.amazon.com/Windows-Forms-Programming-Chris-Sells/dp/0321116208) - - - -[C# Coding Conventions](http://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx) + * [C# Coding Conventions](http://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx) | 
