diff options
Diffstat (limited to 'csharp.html.markdown')
| -rw-r--r-- | csharp.html.markdown | 353 | 
1 files changed, 320 insertions, 33 deletions
| diff --git a/csharp.html.markdown b/csharp.html.markdown index 442700a6..b965c2d4 100644 --- a/csharp.html.markdown +++ b/csharp.html.markdown @@ -14,20 +14,22 @@ filename: LearnCSharp.cs  C# is an elegant and type-safe object-oriented language that enables developers to build a variety of secure and robust applications that run on the .NET Framework. -[Read more here.](http://msdn.microsoft.com/en-us/library/vstudio/z1zx9t92.aspx) +[Read more here.](https://docs.microsoft.com/dotnet/csharp/getting-started/introduction-to-the-csharp-language-and-the-net-framework)  ```c#  // Single-line comments start with // +  /*  Multi-line comments look like this  */ +  /// <summary>  /// 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) {} +public void MethodOrClassOrOtherWithParsableHelp(string firstParam) {}  // Specify the namespaces this source code will be using  // The namespaces below are all part of the standard .NET Framework Class Library @@ -132,6 +134,12 @@ namespace Learning.CSharp              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"; @@ -248,7 +256,7 @@ on a new line! ""Wow!"", the masses cried";              int fooWhile = 0;              while (fooWhile < 100)              { -                //Iterated 100 times, fooWhile 0->99 +                // Iterated 100 times, fooWhile 0->99                  fooWhile++;              } @@ -267,10 +275,10 @@ on a new line! ""Wow!"", the masses cried";              } while (fooDoWhile < 100); -            //for loop structure => for(<start_statement>; <conditional>; <step>) +            // for loop structure => for(<start_statement>; <conditional>; <step>)              for (int fooFor = 0; fooFor < 10; fooFor++)              { -                //Iterated 10 times, fooFor 0->9 +                // Iterated 10 times, fooFor 0->9              }              // For Each Loop @@ -281,7 +289,7 @@ on a new line! ""Wow!"", the masses cried";              // (The ToCharArray() could be removed, because a string also implements IEnumerable)              foreach (char character in "Hello World".ToCharArray())              { -                //Iterated over all the characters in the string +                // Iterated over all the characters in the string              }              // Switch Case @@ -323,7 +331,7 @@ on a new line! ""Wow!"", the masses cried";              // Convert String To Integer              // this will throw a FormatException on failure -            int.Parse("123");//returns an integer version of "123" +            int.Parse("123"); // returns an integer version of "123"              // try parse will default to type default on failure              // in this case: 0 @@ -338,7 +346,7 @@ on a new line! ""Wow!"", the masses cried";              tryInt.ToString();              // Casting -            // Cast decimal 15 to a int +            // Cast decimal 15 to an int              // and then implicitly cast to long              long x = (int) 15M;          } @@ -367,7 +375,7 @@ on a new line! ""Wow!"", the masses cried";              Console.Read();          } // End main method -        // CONSOLE ENTRY A console application must have a main method as an entry point +        // CONSOLE ENTRY - A console application must have a main method as an entry point          public static void Main(string[] args)          {              OtherInterestingFeatures(); @@ -398,7 +406,7 @@ on a new line! ""Wow!"", the masses cried";              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 +            // 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          } @@ -546,7 +554,7 @@ on a new line! ""Wow!"", the masses cried";              }              // PARALLEL FRAMEWORK -            // http://blogs.msdn.com/b/csharpfaq/archive/2010/06/01/parallel-programming-in-net-framework-4-getting-started.aspx +            // https://devblogs.microsoft.com/csharpfaq/parallel-programming-in-net-framework-4-getting-started/              var words = new List<string> {"dog", "cat", "horse", "pony"}; @@ -558,11 +566,11 @@ on a new line! ""Wow!"", the masses cried";                  }              ); -            //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 +            // 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(); @@ -593,7 +601,7 @@ 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 @@ -613,7 +621,7 @@ 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 +            // Now the query runs, but opens a reader, so only populates as you iterate through              foreach (string bike in query)                  Console.WriteLine(result); @@ -634,6 +642,54 @@ on a new line! ""Wow!"", the masses cried";          }      } + +    // 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, +        // i.e. 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. @@ -671,10 +727,10 @@ on a new line! ""Wow!"", the masses cried";          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";  +        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). @@ -711,7 +767,7 @@ on a new line! ""Wow!"", the masses cried";          // Before .NET 4: (aBike.Accessories & Bicycle.BikeAccessories.Bell) == Bicycle.BikeAccessories.Bell          public BikeAccessories Accessories { get; set; } -        // Static members belong to the type itself rather then specific object. +        // 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);          public static int BicyclesCreated { get; set; } @@ -811,7 +867,7 @@ on a new line! ""Wow!"", the masses cried";              }          } -        //Method to display the attribute values of this Object. +        // Method to display the attribute values of this Object.          public virtual string Info()          {              return "Gear: " + Gear + @@ -906,7 +962,7 @@ on a new line! ""Wow!"", the masses cried";      /// <summary>      /// 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 +    /// https://docs.microsoft.com/ef/ef6/modeling/code-first/workflows/new-database      /// </summary>      public class BikeRepository : DbContext      { @@ -949,6 +1005,7 @@ on a new line! ""Wow!"", the masses cried";      // 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; } @@ -961,6 +1018,9 @@ on a new line! ""Wow!"", the masses cried";          {              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");          }      } @@ -1006,15 +1066,242 @@ on a new line! ""Wow!"", the masses cried";              // 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   * Attributes - * async/await, pragma directives - * Exception filters - * `using static` + * async/await   * Web Development   	* ASP.NET MVC & WebApi (new)   	* ASP.NET Web Forms (old) @@ -1025,13 +1312,13 @@ on a new line! ""Wow!"", the masses cried";  ## Further Reading + * [C# language reference](https://docs.microsoft.com/dotnet/csharp/language-reference/) + * [Learn .NET](https://dotnet.microsoft.com/learn) + * [C# Coding Conventions](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions)   * [DotNetPerls](http://www.dotnetperls.com)   * [C# in Depth](http://manning.com/skeet2) - * [Programming C#](http://shop.oreilly.com/product/0636920024064.do) - * [LINQ](http://shop.oreilly.com/product/9780596519254.do) - * [MSDN Library](http://msdn.microsoft.com/en-us/library/618ayhy6.aspx) - * [ASP.NET MVC Tutorials](http://www.asp.net/mvc/tutorials) - * [ASP.NET Web Matrix Tutorials](http://www.asp.net/web-pages/tutorials) - * [ASP.NET Web Forms Tutorials](http://www.asp.net/web-forms/tutorials) + * [Programming C# 5.0](http://shop.oreilly.com/product/0636920024064.do) + * [LINQ Pocket Reference](http://shop.oreilly.com/product/9780596519254.do)   * [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) + * [freeCodeCamp - C# Tutorial for Beginners](https://www.youtube.com/watch?v=GhQdlIFylQ8) + 
\ No newline at end of file | 
