From 89b794b0e3d453ffce05f8711ea3443bbc59af22 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Tue, 19 May 2020 15:19:50 -0400 Subject: [PATCH 01/11] first draft finished. --- docs/csharp/methods.md | 2 +- docs/csharp/toc.yml | 24 +- .../Snippets}/arrays/Program.cs | 19 ++ .../Snippets}/arrays/access-by-line.txt | 0 .../Snippets}/arrays/arrays.csproj | 0 .../Snippets}/attributes/Program.cs | 5 + .../Snippets}/attributes/access-by-line.txt | 0 .../Snippets}/attributes/attributes.csproj | 0 .../Snippets}/classes-and-objects/Color.cs | 2 + .../Snippets}/classes-and-objects/Entity.cs | 4 + .../classes-and-objects/Expressions.cs | 4 + .../classes-and-objects/ListBasedExamples.cs | 13 + .../classes-and-objects/OutExample.cs | 2 + .../classes-and-objects/Overloading.cs | 3 +- .../Snippets}/classes-and-objects/Pair.cs | 2 + .../Snippets}/classes-and-objects/Point.cs | 16 + .../Snippets}/classes-and-objects/Program.cs | 15 +- .../classes-and-objects/RefExample.cs | 2 + .../Snippets}/classes-and-objects/Squares.cs | 2 + .../classes-and-objects/access-by-line.txt | 0 .../classes-and-objects.csproj | 0 .../Snippets}/delegates/Program.cs | 10 +- .../Snippets}/delegates/access-by-line.txt | 0 .../Snippets}/delegates/delegates.csproj | 0 .../tour-of-csharp/Snippets}/hello/Program.cs | 0 .../Snippets}/hello/hello.csproj | 0 .../Snippets}/interfaces/Program.cs | 13 +- .../Snippets}/interfaces/access-by-line.txt | 0 .../Snippets}/interfaces/interfaces.csproj | 0 .../Snippets/program-structure/Program.cs | 57 ++++ .../program-structure.csproj | 0 .../Snippets/types-and-variables/Program.cs | 50 ++++ .../types-and-variables.csproj | 0 docs/csharp/tour-of-csharp/arrays.md | 43 --- docs/csharp/tour-of-csharp/attributes.md | 29 -- docs/csharp/tour-of-csharp/delegates.md | 28 -- docs/csharp/tour-of-csharp/expressions.md | 28 -- docs/csharp/tour-of-csharp/features.md | 129 +++++++++ docs/csharp/tour-of-csharp/index.md | 152 ++++++---- docs/csharp/tour-of-csharp/interfaces.md | 38 --- ...-objects.md => program-building-blocks.md} | 204 ++++++------- .../tour-of-csharp/program-structure.md | 56 ---- docs/csharp/tour-of-csharp/statements.md | 108 ------- .../tour-of-csharp/types-and-variables.md | 107 ------- docs/csharp/tour-of-csharp/types.md | 104 +++++++ docs/csharp/tutorials/inheritance.md | 1 - .../MakeConst/AnalyzerReleases.Shipped.md | 3 + .../MakeConst/AnalyzerReleases.Unshipped.md | 3 + .../csharp/tour/program-structure/Program.cs | 53 ---- .../tour/program-structure/access-by-line.txt | 1 - .../csharp/tour/statements/Program.cs | 274 ------------------ .../csharp/tour/statements/access-by-line.txt | 1 - .../csharp/tour/statements/statements.csproj | 8 - .../tour/types-and-variables/Program.cs | 10 - .../types-and-variables/access-by-line.txt | 2 - 55 files changed, 665 insertions(+), 962 deletions(-) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/arrays/Program.cs (67%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/arrays/access-by-line.txt (100%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/arrays/arrays.csproj (100%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/attributes/Program.cs (95%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/attributes/access-by-line.txt (100%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/attributes/attributes.csproj (100%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/classes-and-objects/Color.cs (90%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/classes-and-objects/Entity.cs (91%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/classes-and-objects/Expressions.cs (95%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/classes-and-objects/ListBasedExamples.cs (92%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/classes-and-objects/OutExample.cs (91%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/classes-and-objects/Overloading.cs (96%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/classes-and-objects/Pair.cs (73%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/classes-and-objects/Point.cs (53%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/classes-and-objects/Program.cs (82%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/classes-and-objects/RefExample.cs (90%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/classes-and-objects/Squares.cs (88%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/classes-and-objects/access-by-line.txt (100%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/classes-and-objects/classes-and-objects.csproj (100%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/delegates/Program.cs (88%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/delegates/access-by-line.txt (100%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/delegates/delegates.csproj (100%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/hello/Program.cs (100%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/hello/hello.csproj (100%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/interfaces/Program.cs (80%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/interfaces/access-by-line.txt (100%) rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/interfaces/interfaces.csproj (100%) create mode 100644 docs/csharp/tour-of-csharp/Snippets/program-structure/Program.cs rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/program-structure/program-structure.csproj (100%) create mode 100644 docs/csharp/tour-of-csharp/Snippets/types-and-variables/Program.cs rename {samples/snippets/csharp/tour => docs/csharp/tour-of-csharp/Snippets}/types-and-variables/types-and-variables.csproj (100%) delete mode 100644 docs/csharp/tour-of-csharp/arrays.md delete mode 100644 docs/csharp/tour-of-csharp/attributes.md delete mode 100644 docs/csharp/tour-of-csharp/delegates.md delete mode 100644 docs/csharp/tour-of-csharp/expressions.md create mode 100644 docs/csharp/tour-of-csharp/features.md delete mode 100644 docs/csharp/tour-of-csharp/interfaces.md rename docs/csharp/tour-of-csharp/{classes-and-objects.md => program-building-blocks.md} (67%) delete mode 100644 docs/csharp/tour-of-csharp/program-structure.md delete mode 100644 docs/csharp/tour-of-csharp/statements.md delete mode 100644 docs/csharp/tour-of-csharp/types-and-variables.md create mode 100644 docs/csharp/tour-of-csharp/types.md create mode 100644 samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Shipped.md create mode 100644 samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Unshipped.md delete mode 100644 samples/snippets/csharp/tour/program-structure/Program.cs delete mode 100644 samples/snippets/csharp/tour/program-structure/access-by-line.txt delete mode 100644 samples/snippets/csharp/tour/statements/Program.cs delete mode 100644 samples/snippets/csharp/tour/statements/access-by-line.txt delete mode 100644 samples/snippets/csharp/tour/statements/statements.csproj delete mode 100644 samples/snippets/csharp/tour/types-and-variables/Program.cs delete mode 100644 samples/snippets/csharp/tour/types-and-variables/access-by-line.txt diff --git a/docs/csharp/methods.md b/docs/csharp/methods.md index 6606cf24b03dd..3a6fe4d8385fa 100644 --- a/docs/csharp/methods.md +++ b/docs/csharp/methods.md @@ -76,7 +76,7 @@ Types can override inherited members by using the `override` keyword and providi ## Passing parameters -Types in C# are either *value types* or *reference types*. For a list of built-in value types, see [Types and variables](./tour-of-csharp/types-and-variables.md). By default, both value types and reference types are passed to a method by value. +Types in C# are either *value types* or *reference types*. For a list of built-in value types, see [Types](./tour-of-csharp/types.md). By default, both value types and reference types are passed to a method by value. diff --git a/docs/csharp/toc.yml b/docs/csharp/toc.yml index 6b0f1ec7a3165..01f3d9a020c97 100644 --- a/docs/csharp/toc.yml +++ b/docs/csharp/toc.yml @@ -72,24 +72,12 @@ items: - name: Introduction href: tour-of-csharp/index.md - - name: Program Structure - href: tour-of-csharp/program-structure.md - - name: Types and Variables - href: tour-of-csharp/types-and-variables.md - - name: Expressions - href: tour-of-csharp/expressions.md - - name: Statements - href: tour-of-csharp/statements.md - - name: Classes and objects - href: tour-of-csharp/classes-and-objects.md - - name: Arrays - href: tour-of-csharp/arrays.md - - name: Interfaces - href: tour-of-csharp/interfaces.md - - name: Delegates - href: tour-of-csharp/delegates.md - - name: Attributes - href: tour-of-csharp/attributes.md + - name: Types + href: tour-of-csharp/types.md + - name: Program building blocks + href: tour-of-csharp/program-building-blocks.md + - name: Features of C# + href: tour-of-csharp/features.md - name: What's new in C# items: - name: C# 8.0 diff --git a/samples/snippets/csharp/tour/arrays/Program.cs b/docs/csharp/tour-of-csharp/Snippets/arrays/Program.cs similarity index 67% rename from samples/snippets/csharp/tour/arrays/Program.cs rename to docs/csharp/tour-of-csharp/Snippets/arrays/Program.cs index c5f4f90aa9cf0..c370d857166b4 100644 --- a/samples/snippets/csharp/tour/arrays/Program.cs +++ b/docs/csharp/tour-of-csharp/Snippets/arrays/Program.cs @@ -1,5 +1,6 @@ namespace ArraySample { + // using System; class ArrayExample { @@ -16,41 +17,59 @@ static void Main() } } } + // class SampleCode { static void ExampleOne() { + // int[] a1 = new int[10]; int[,] a2 = new int[10, 5]; int[,,] a3 = new int[10, 5, 2]; + // } static void ExampleTwo() { + // int[][] a = new int[3][]; a[0] = new int[10]; a[1] = new int[5]; a[2] = new int[20]; + // } static void ExampleThree() { + // int[] a = new int[] {1, 2, 3}; + // } static void ExampleFour() { + // int[] a = {1, 2, 3}; + // } static void ExampleFive() { + // int[] t = new int[3]; t[0] = 1; t[1] = 2; t[2] = 3; int[] a = t; + // + + // + foreach(int item in a) + { + Console.WriteLine(item); + } + // } } } diff --git a/samples/snippets/csharp/tour/arrays/access-by-line.txt b/docs/csharp/tour-of-csharp/Snippets/arrays/access-by-line.txt similarity index 100% rename from samples/snippets/csharp/tour/arrays/access-by-line.txt rename to docs/csharp/tour-of-csharp/Snippets/arrays/access-by-line.txt diff --git a/samples/snippets/csharp/tour/arrays/arrays.csproj b/docs/csharp/tour-of-csharp/Snippets/arrays/arrays.csproj similarity index 100% rename from samples/snippets/csharp/tour/arrays/arrays.csproj rename to docs/csharp/tour-of-csharp/Snippets/arrays/arrays.csproj diff --git a/samples/snippets/csharp/tour/attributes/Program.cs b/docs/csharp/tour-of-csharp/Snippets/attributes/Program.cs similarity index 95% rename from samples/snippets/csharp/tour/attributes/Program.cs rename to docs/csharp/tour-of-csharp/Snippets/attributes/Program.cs index 343feb80d97e0..0f2865fee7b66 100644 --- a/samples/snippets/csharp/tour/attributes/Program.cs +++ b/docs/csharp/tour-of-csharp/Snippets/attributes/Program.cs @@ -1,5 +1,6 @@ namespace AttributeSample { + // using System; public class HelpAttribute: Attribute @@ -18,7 +19,9 @@ public string Topic { set { topic = value; } } } + // + // [Help("https://docs.microsoft.com/dotnet/csharp/tour-of-csharp/attributes")] public class Widget { @@ -26,6 +29,8 @@ public class Widget Topic = "Display")] public void Display(string text) {} } + // + public class Program { diff --git a/samples/snippets/csharp/tour/attributes/access-by-line.txt b/docs/csharp/tour-of-csharp/Snippets/attributes/access-by-line.txt similarity index 100% rename from samples/snippets/csharp/tour/attributes/access-by-line.txt rename to docs/csharp/tour-of-csharp/Snippets/attributes/access-by-line.txt diff --git a/samples/snippets/csharp/tour/attributes/attributes.csproj b/docs/csharp/tour-of-csharp/Snippets/attributes/attributes.csproj similarity index 100% rename from samples/snippets/csharp/tour/attributes/attributes.csproj rename to docs/csharp/tour-of-csharp/Snippets/attributes/attributes.csproj diff --git a/samples/snippets/csharp/tour/classes-and-objects/Color.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Color.cs similarity index 90% rename from samples/snippets/csharp/tour/classes-and-objects/Color.cs rename to docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Color.cs index a1278407e2626..15fc3431e0762 100644 --- a/samples/snippets/csharp/tour/classes-and-objects/Color.cs +++ b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Color.cs @@ -1,5 +1,6 @@ namespace ClassesAndObjects { + // public class Color { public static readonly Color Black = new Color(0, 0, 0); @@ -15,4 +16,5 @@ public Color(byte r, byte g, byte b) this.b = b; } } + // } diff --git a/samples/snippets/csharp/tour/classes-and-objects/Entity.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Entity.cs similarity index 91% rename from samples/snippets/csharp/tour/classes-and-objects/Entity.cs rename to docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Entity.cs index f6e911da8ce95..b84560dc019b7 100644 --- a/samples/snippets/csharp/tour/classes-and-objects/Entity.cs +++ b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Entity.cs @@ -1,5 +1,6 @@ namespace ClassesAndObjects { + // using System; class EntityExample { @@ -13,6 +14,8 @@ public static void Usage() Console.WriteLine(Entity.GetNextSerialNo()); // Outputs "1002" } } + // + // class Entity { static int nextSerialNo; @@ -34,4 +37,5 @@ public static void SetNextSerialNo(int value) nextSerialNo = value; } } + // } \ No newline at end of file diff --git a/samples/snippets/csharp/tour/classes-and-objects/Expressions.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Expressions.cs similarity index 95% rename from samples/snippets/csharp/tour/classes-and-objects/Expressions.cs rename to docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Expressions.cs index f3c2ee5c12c26..e0d5c5db0d772 100644 --- a/samples/snippets/csharp/tour/classes-and-objects/Expressions.cs +++ b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Expressions.cs @@ -1,5 +1,6 @@ namespace ClassesAndObjects { + // using System; using System.Collections.Generic; public abstract class Expression @@ -59,10 +60,12 @@ public override double Evaluate(Dictionary vars) throw new Exception("Unknown operator"); } } + // } namespace ClassesAndObjects { + // using System; using System.Collections.Generic; class InheritanceExample @@ -87,4 +90,5 @@ public static void ExampleUsage() Console.WriteLine(e.Evaluate(vars)); // Outputs "16.5" } } + // } \ No newline at end of file diff --git a/samples/snippets/csharp/tour/classes-and-objects/ListBasedExamples.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/ListBasedExamples.cs similarity index 92% rename from samples/snippets/csharp/tour/classes-and-objects/ListBasedExamples.cs rename to docs/csharp/tour-of-csharp/Snippets/classes-and-objects/ListBasedExamples.cs index a11a133134bb5..743053afaabce 100644 --- a/samples/snippets/csharp/tour/classes-and-objects/ListBasedExamples.cs +++ b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/ListBasedExamples.cs @@ -1,6 +1,7 @@ namespace ListExamples { using System; + // public class MyList { // Constant @@ -87,25 +88,31 @@ static bool Equals(MyList a, MyList b) public static bool operator !=(MyList a, MyList b) => !Equals(a, b); } + // public class ExampleCode { public static void ListExampleOne() { + // MyList list1 = new MyList(); MyList list2 = new MyList(10); + // } public static void ListExampleTwo() { + // MyList names = new MyList(); names.Capacity = 100; // Invokes set accessor int i = names.Count; // Invokes get accessor int j = names.Capacity; // Invokes get accessor + // } public static void ListExampleThree() { + // MyList names = new MyList(); names.Add("Liz"); names.Add("Martha"); @@ -115,9 +122,11 @@ public static void ListExampleThree() string s = names[i]; names[i] = s.ToUpper(); } + // } public static void ListExampleFour() { + // MyList a = new MyList(); a.Add(1); a.Add(2); @@ -127,8 +136,11 @@ public static void ListExampleFour() Console.WriteLine(a == b); // Outputs "True" b.Add(3); Console.WriteLine(a == b); // Outputs "False" + // } } + + // class EventExample { static int changeCount; @@ -146,4 +158,5 @@ public static void Usage() Console.WriteLine(changeCount); // Outputs "3" } } + // } \ No newline at end of file diff --git a/samples/snippets/csharp/tour/classes-and-objects/OutExample.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/OutExample.cs similarity index 91% rename from samples/snippets/csharp/tour/classes-and-objects/OutExample.cs rename to docs/csharp/tour-of-csharp/Snippets/classes-and-objects/OutExample.cs index 998135fb3d8a6..838b4b9ebee1a 100644 --- a/samples/snippets/csharp/tour/classes-and-objects/OutExample.cs +++ b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/OutExample.cs @@ -1,6 +1,7 @@ namespace ClassesAndObjects { using System; + // class OutExample { static void Divide(int x, int y, out int result, out int remainder) @@ -14,4 +15,5 @@ public static void OutUsage() Console.WriteLine("{0} {1}", res, rem); // Outputs "3 1" } } + // } diff --git a/samples/snippets/csharp/tour/classes-and-objects/Overloading.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Overloading.cs similarity index 96% rename from samples/snippets/csharp/tour/classes-and-objects/Overloading.cs rename to docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Overloading.cs index 0866c39913f39..61821daf8f82d 100644 --- a/samples/snippets/csharp/tour/classes-and-objects/Overloading.cs +++ b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Overloading.cs @@ -1,5 +1,6 @@ namespace ClassesAndObjects { + // using System; class OverloadingExample { @@ -39,5 +40,5 @@ public static void UsageExample() F(1, 1); // Invokes F(double, double) } } - + // } \ No newline at end of file diff --git a/samples/snippets/csharp/tour/classes-and-objects/Pair.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Pair.cs similarity index 73% rename from samples/snippets/csharp/tour/classes-and-objects/Pair.cs rename to docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Pair.cs index ce091cd72d8dd..3ead20ba71ce0 100644 --- a/samples/snippets/csharp/tour/classes-and-objects/Pair.cs +++ b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Pair.cs @@ -1,8 +1,10 @@ namespace ClassesAndObjects { + // public class Pair { public TFirst First; public TSecond Second; } + // } \ No newline at end of file diff --git a/samples/snippets/csharp/tour/classes-and-objects/Point.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Point.cs similarity index 53% rename from samples/snippets/csharp/tour/classes-and-objects/Point.cs rename to docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Point.cs index 2e83b13b6fc53..6457c3af638a3 100644 --- a/samples/snippets/csharp/tour/classes-and-objects/Point.cs +++ b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Point.cs @@ -1,5 +1,6 @@ namespace ClassesAndObjects { + // public class Point { public int x, y; @@ -9,6 +10,8 @@ public Point(int x, int y) this.y = y; } } + // + // public class Point3D: Point { public int z; @@ -18,4 +21,17 @@ public Point3D(int x, int y, int z) : this.z = z; } } + // +} + +namespace DeclareTypes +{ + // + public struct Point + { + public double X { get; } + public double Y { get; } + public Point(double x, double y) => (X, Y) = (x, y); + } + // } \ No newline at end of file diff --git a/samples/snippets/csharp/tour/classes-and-objects/Program.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Program.cs similarity index 82% rename from samples/snippets/csharp/tour/classes-and-objects/Program.cs rename to docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Program.cs index dd7ab6425d886..e067b50ef9604 100644 --- a/samples/snippets/csharp/tour/classes-and-objects/Program.cs +++ b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Program.cs @@ -6,25 +6,32 @@ public class Program { static void PointExample() { + // Point p1 = new Point(0, 0); Point p2 = new Point(10, 20); + // } static void PairExample() { + // Pair pair = new Pair { First = 1, Second = "two" }; int i = pair.First; // TFirst is int string s = pair.Second; // TSecond is string + // } static void Point3DExample() { + // Point a = new Point(10, 20); Point b = new Point3D(10, 20, 30); + // } static void StringFormatExample() { + // int x = 3, y = 4, z = 5; string s = "x={0} y={1} z={2}"; @@ -33,14 +40,17 @@ static void StringFormatExample() args[1] = y; args[2] = z; Console.WriteLine(s, args); + // } static void ExpressionExample() { + // Expression e = new Operation( new VariableReference("x"), '+', new Constant(3)); + // } public static void Main(string[] args) @@ -51,8 +61,10 @@ public static void Main(string[] args) RefExample.SwapExample(); OutExample.OutUsage(); + // int x = 3, y = 4, z = 5; Console.WriteLine("x={0} y={1} z={2}", x, y, z); + // Squares.WriteSquares(); @@ -75,11 +87,12 @@ public static void Main(string[] args) namespace Snippets { + // public class Console { public static void Write(string fmt, params object[] args) { } public static void WriteLine(string fmt, params object[] args) { } // ... } - + // } diff --git a/samples/snippets/csharp/tour/classes-and-objects/RefExample.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/RefExample.cs similarity index 90% rename from samples/snippets/csharp/tour/classes-and-objects/RefExample.cs rename to docs/csharp/tour-of-csharp/Snippets/classes-and-objects/RefExample.cs index c95895780400a..b9f821df406a4 100644 --- a/samples/snippets/csharp/tour/classes-and-objects/RefExample.cs +++ b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/RefExample.cs @@ -1,6 +1,7 @@ namespace ClassesAndObjects { using System; + // class RefExample { static void Swap(ref int x, ref int y) @@ -16,4 +17,5 @@ public static void SwapExample() Console.WriteLine($"{i} {j}"); // Outputs "2 1" } } + // } \ No newline at end of file diff --git a/samples/snippets/csharp/tour/classes-and-objects/Squares.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Squares.cs similarity index 88% rename from samples/snippets/csharp/tour/classes-and-objects/Squares.cs rename to docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Squares.cs index 097aa782869ef..f2ceb47b87c80 100644 --- a/samples/snippets/csharp/tour/classes-and-objects/Squares.cs +++ b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Squares.cs @@ -1,6 +1,7 @@ namespace ClassesAndObjects { using System; + // class Squares { public static void WriteSquares() @@ -15,4 +16,5 @@ public static void WriteSquares() } } } + // } \ No newline at end of file diff --git a/samples/snippets/csharp/tour/classes-and-objects/access-by-line.txt b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/access-by-line.txt similarity index 100% rename from samples/snippets/csharp/tour/classes-and-objects/access-by-line.txt rename to docs/csharp/tour-of-csharp/Snippets/classes-and-objects/access-by-line.txt diff --git a/samples/snippets/csharp/tour/classes-and-objects/classes-and-objects.csproj b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/classes-and-objects.csproj similarity index 100% rename from samples/snippets/csharp/tour/classes-and-objects/classes-and-objects.csproj rename to docs/csharp/tour-of-csharp/Snippets/classes-and-objects/classes-and-objects.csproj diff --git a/samples/snippets/csharp/tour/delegates/Program.cs b/docs/csharp/tour-of-csharp/Snippets/delegates/Program.cs similarity index 88% rename from samples/snippets/csharp/tour/delegates/Program.cs rename to docs/csharp/tour-of-csharp/Snippets/delegates/Program.cs index 016220efc1c1e..2b492a3de10d4 100644 --- a/samples/snippets/csharp/tour/delegates/Program.cs +++ b/docs/csharp/tour-of-csharp/Snippets/delegates/Program.cs @@ -1,5 +1,6 @@ namespace DelegateTour { + // using System; delegate double Function(double x); class Multiplier @@ -16,10 +17,6 @@ public double Multiply(double x) } class DelegateExample { - static double Square(double x) - { - return x * x; - } static double[] Apply(double[] a, Function f) { double[] result = new double[a.Length]; @@ -29,19 +26,22 @@ static double[] Apply(double[] a, Function f) static void Main() { double[] a = {0.0, 0.5, 1.0}; - double[] squares = Apply(a, Square); + double[] squares = Apply(a, (x) => x * x); double[] sines = Apply(a, Math.Sin); Multiplier m = new Multiplier(2.0); double[] doubles = Apply(a, m.Multiply); } } + // class Lambda { static void ApplyDelegate() { double[] a = {0.0, 0.5, 1.0}; + // double[] doubles = Apply(a, (double x) => x * 2.0); + // } static double[] Apply(double[] a, Function f) { diff --git a/samples/snippets/csharp/tour/delegates/access-by-line.txt b/docs/csharp/tour-of-csharp/Snippets/delegates/access-by-line.txt similarity index 100% rename from samples/snippets/csharp/tour/delegates/access-by-line.txt rename to docs/csharp/tour-of-csharp/Snippets/delegates/access-by-line.txt diff --git a/samples/snippets/csharp/tour/delegates/delegates.csproj b/docs/csharp/tour-of-csharp/Snippets/delegates/delegates.csproj similarity index 100% rename from samples/snippets/csharp/tour/delegates/delegates.csproj rename to docs/csharp/tour-of-csharp/Snippets/delegates/delegates.csproj diff --git a/samples/snippets/csharp/tour/hello/Program.cs b/docs/csharp/tour-of-csharp/Snippets/hello/Program.cs similarity index 100% rename from samples/snippets/csharp/tour/hello/Program.cs rename to docs/csharp/tour-of-csharp/Snippets/hello/Program.cs diff --git a/samples/snippets/csharp/tour/hello/hello.csproj b/docs/csharp/tour-of-csharp/Snippets/hello/hello.csproj similarity index 100% rename from samples/snippets/csharp/tour/hello/hello.csproj rename to docs/csharp/tour-of-csharp/Snippets/hello/hello.csproj diff --git a/samples/snippets/csharp/tour/interfaces/Program.cs b/docs/csharp/tour-of-csharp/Snippets/interfaces/Program.cs similarity index 80% rename from samples/snippets/csharp/tour/interfaces/Program.cs rename to docs/csharp/tour-of-csharp/Snippets/interfaces/Program.cs index 91d76186d0a06..fb5251a003830 100644 --- a/samples/snippets/csharp/tour/interfaces/Program.cs +++ b/docs/csharp/tour-of-csharp/Snippets/interfaces/Program.cs @@ -2,6 +2,7 @@ namespace Interfaces { + // interface IControl { void Paint(); @@ -15,7 +16,9 @@ interface IListBox: IControl void SetItems(string[] items); } interface IComboBox: ITextBox, IListBox {} + // + // interface IDataBound { void Bind(Binder b); @@ -25,21 +28,26 @@ public class EditBox: IControl, IDataBound public void Paint() { } public void Bind(Binder b) { } } + // public class Program { static void UsageOne() { + // EditBox editBox = new EditBox(); IControl control = editBox; IDataBound dataBound = editBox; + // } static void UsageTwo() { + // object obj = new EditBox(); IControl control = (IControl)obj; IDataBound dataBound = (IDataBound)obj; + // } public static void Main(string[] args) @@ -57,21 +65,24 @@ namespace ExplicitInterface { using Interfaces; + // public class EditBox: IControl, IDataBound { void IControl.Paint() { } void IDataBound.Bind(Binder b) { } } + // class UsageCode { static void Example() { - /* + /* EditBox editBox = new EditBox(); editBox.Paint(); // Error, no such method IControl control = editBox; control.Paint(); // Ok + */ } } diff --git a/samples/snippets/csharp/tour/interfaces/access-by-line.txt b/docs/csharp/tour-of-csharp/Snippets/interfaces/access-by-line.txt similarity index 100% rename from samples/snippets/csharp/tour/interfaces/access-by-line.txt rename to docs/csharp/tour-of-csharp/Snippets/interfaces/access-by-line.txt diff --git a/samples/snippets/csharp/tour/interfaces/interfaces.csproj b/docs/csharp/tour-of-csharp/Snippets/interfaces/interfaces.csproj similarity index 100% rename from samples/snippets/csharp/tour/interfaces/interfaces.csproj rename to docs/csharp/tour-of-csharp/Snippets/interfaces/interfaces.csproj diff --git a/docs/csharp/tour-of-csharp/Snippets/program-structure/Program.cs b/docs/csharp/tour-of-csharp/Snippets/program-structure/Program.cs new file mode 100644 index 0000000000000..e3a8af4b6a210 --- /dev/null +++ b/docs/csharp/tour-of-csharp/Snippets/program-structure/Program.cs @@ -0,0 +1,57 @@ +// +using System; +namespace Acme.Collections +{ + public class Stack + { + Entry top; + public void Push(T data) + { + top = new Entry(top, data); + } + + public T Pop() + { + if (top == null) + { + throw new InvalidOperationException(); + } + T result = top.data; + top = top.next; + return result; + } + + class Entry + { + public Entry next; + public T data; + public Entry(Entry next, T data) + { + this.next = next; + this.data = data; + } + } + } +} +// + +namespace StackExample +{ + // + using System; + using Acme.Collections; + class Example + { + static void Main() + { + Stack s = new Stack(); + s.Push(1); // stack contains 1 + s.Push(10); // stack contains 1, 10 + s.Push(100); // stack contains 1, 10, 100 + Console.WriteLine(s.Pop()); // stack contains 1, 10 + Console.WriteLine(s.Pop()); // stack contains 1 + Console.WriteLine(s.Pop()); // stack is empty + } + } + // +} diff --git a/samples/snippets/csharp/tour/program-structure/program-structure.csproj b/docs/csharp/tour-of-csharp/Snippets/program-structure/program-structure.csproj similarity index 100% rename from samples/snippets/csharp/tour/program-structure/program-structure.csproj rename to docs/csharp/tour-of-csharp/Snippets/program-structure/program-structure.csproj diff --git a/docs/csharp/tour-of-csharp/Snippets/types-and-variables/Program.cs b/docs/csharp/tour-of-csharp/Snippets/types-and-variables/Program.cs new file mode 100644 index 0000000000000..4d85d1d45a4f3 --- /dev/null +++ b/docs/csharp/tour-of-csharp/Snippets/types-and-variables/Program.cs @@ -0,0 +1,50 @@ +using System; +class BoxingExample +{ + // + // A traditional enumeration of some root vegetables. + public enum SomeRootVegetables + { + HorseRadish, + Radish, + Turnip + } + // + + // + // A bit field or flag enumeration of harvesting seasons. + [Flags] + public enum Seasons + { + None = 0, + Summer = 1, + Autumn = 2, + Winter = 4, + Spring = 8, + All = Summer | Autumn | Winter | Spring + } + // + + static void Main() + { + // + int i = 123; + Console.WriteLine($"Value of i: {i}"); + object o = i; // Boxing + Console.WriteLine($"Initial value of o: {o}"); + o = 456; + Console.WriteLine($"Modified value of o: {o}"); + int j = (int)o; // Unboxing + Console.WriteLine($"Value of unboxed j: {j}"); + Console.WriteLine($"Final value of i: {i}"); + // + + // + var turnip = SomeRootVegetables.Turnip; + + var spring = Seasons.Spring; + var startingOnEquinox = Seasons.Spring | Seasons.Autumn; + var theYear = Seasons.All; + // + } +} diff --git a/samples/snippets/csharp/tour/types-and-variables/types-and-variables.csproj b/docs/csharp/tour-of-csharp/Snippets/types-and-variables/types-and-variables.csproj similarity index 100% rename from samples/snippets/csharp/tour/types-and-variables/types-and-variables.csproj rename to docs/csharp/tour-of-csharp/Snippets/types-and-variables/types-and-variables.csproj diff --git a/docs/csharp/tour-of-csharp/arrays.md b/docs/csharp/tour-of-csharp/arrays.md deleted file mode 100644 index cc031bb401068..0000000000000 --- a/docs/csharp/tour-of-csharp/arrays.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: C# Arrays - A tour of the C# language -description: Arrays are the most basic collection type in the C# language -ms.date: 02/27/2020 -ms.assetid: a440704c-9e88-4c75-97dd-bfe30ca0fb97 ---- - -# Arrays - -An ***array*** is a data structure that contains a number of variables that are accessed through computed indices. The variables contained in an array, also called the ***elements*** of the array, are all of the same type, and this type is called the ***element type*** of the array. - -Array types are reference types, and the declaration of an array variable simply sets aside space for a reference to an array instance. Actual array instances are created dynamically at runtime using the new operator. The new operation specifies the ***length*** of the new array instance, which is then fixed for the lifetime of the instance. The indices of the elements of an array range from `0` to `Length - 1`. The `new` operator automatically initializes the elements of an array to their default value, which, for example, is zero for all numeric types and `null` for all reference types. - -The following example creates an array of `int` elements, initializes the array, and prints out the contents of the array. - -[!code-csharp[ArraySample](../../../samples/snippets/csharp/tour/arrays/Program.cs#L3-L18)] - -This example creates and operates on a ***single-dimensional array***. C# also supports ***multi-dimensional arrays***. The number of dimensions of an array type, also known as the ***rank*** of the array type, is one plus the number of commas written between the square brackets of the array type. The following example allocates a single-dimensional, a two-dimensional, and a three-dimensional array, respectively. - -[!code-csharp[ArrayRank](../../../samples/snippets/csharp/tour/arrays/Program.cs#L24-L26)] - -The `a1` array contains 10 elements, the `a2` array contains 50 (10 × 5) elements, and the `a3` array contains 100 (10 × 5 × 2) elements. -The element type of an array can be any type, including an array type. An array with elements of an array type is sometimes called a ***jagged array*** because the lengths of the element arrays don't all have to be the same. The following example allocates an array of arrays of `int`: - -[!code-csharp[ArrayAllocation](../../../samples/snippets/csharp/tour/arrays/Program.cs#L31-L34)] - -The first line creates an array with three elements, each of type `int[]` and each with an initial value of `null`. The subsequent lines then initialize the three elements with references to individual array instances of varying lengths. - -The new operator permits the initial values of the array elements to be specified using an ***array initializer***, which is a list of expressions written between the delimiters `{` and `}`. The following example allocates and initializes an `int[]` with three elements. - -[!code-csharp[ArrayInitialization](../../../samples/snippets/csharp/tour/arrays/Program.cs#L39-L39)] - -The length of the array is inferred from the number of expressions between { and }. Local variable and field declarations can be shortened further such that the array type does not have to be restated. - -[!code-csharp[ArrayInitialization](../../../samples/snippets/csharp/tour/arrays/Program.cs#L44-L44)] - -Both of the previous examples are equivalent to the following code: - -[!code-csharp[ArrayAssignment](../../../samples/snippets/csharp/tour/arrays/Program.cs#L49-L53)] - ->[!div class="step-by-step"] ->[Previous](classes-and-objects.md) ->[Next](interfaces.md) diff --git a/docs/csharp/tour-of-csharp/attributes.md b/docs/csharp/tour-of-csharp/attributes.md deleted file mode 100644 index 591e93528349c..0000000000000 --- a/docs/csharp/tour-of-csharp/attributes.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: C# Attributes - A tour of the C# language -description: Learn about declarative programming using attributes in C# -ms.date: 02/27/2020 -ms.assetid: 753bcfe2-7ddd-4487-9513-ba70937fc8e9 ---- - -# Attributes - -Types, members, and other entities in a C# program support modifiers that control certain aspects of their behavior. For example, the accessibility of a method is controlled using the `public`, `protected`, `internal`, and `private` modifiers. C# generalizes this capability such that user-defined types of declarative information can be attached to program entities and retrieved at run-time. Programs specify this additional declarative information by defining and using ***attributes***. - -The following example declares a `HelpAttribute` attribute that can be placed on program entities to provide links to their associated documentation. - -[!code-csharp[AttributeDefined](../../../samples/snippets/csharp/tour/attributes/Program.cs#L3-L20)] - -All attribute classes derive from the base class provided by the standard library. Attributes can be applied by giving their name, along with any arguments, inside square brackets just before the associated declaration. If an attribute’s name ends in `Attribute`, that part of the name can be omitted when the attribute is referenced. For example, the `HelpAttribute` can be used as follows. - -[!code-csharp[AttributeApplied](../../../samples/snippets/csharp/tour/attributes/Program.cs#L22-L28)] - -This example attaches a `HelpAttribute` to the `Widget` class. It adds another `HelpAttribute` to the `Display` method in the class. The public constructors of an attribute class control the information that must be provided when the attribute is attached to a program entity. Additional information can be provided by referencing public read-write properties of the attribute class (such as the reference to the `Topic` property previously). - -The metadata defined by attributes can be read and manipulated at runtime using reflection. When a particular attribute is requested using this technique, the constructor for the attribute class is invoked with the information provided in the program source, and the resulting attribute instance is returned. If additional information was provided through properties, those properties are set to the given values before the attribute instance is returned. - -The following code sample demonstrates how to get the `HelpAttribute` instances associated to the `Widget` class and its `Display` method. - -[!code-csharp[AttributeRead](../../../samples/snippets/csharp/tour/attributes/Program.cs#ReadAttributes)] - ->[!div class="step-by-step"] ->[Previous](delegates.md) diff --git a/docs/csharp/tour-of-csharp/delegates.md b/docs/csharp/tour-of-csharp/delegates.md deleted file mode 100644 index 111585c66b864..0000000000000 --- a/docs/csharp/tour-of-csharp/delegates.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: C# Delegates - A tour of the C# language -description: Learn late binding with C# delegates -ms.date: 02/27/2020 -ms.assetid: 3cc27357-3ac2-43a1-aad0-86a77b88f884 ---- - -# Delegates - -A ***delegate type*** represents references to methods with a particular parameter list and return type. Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters. Delegates are similar to the concept of function pointers found in some other languages. Unlike function pointers, delegates are object-oriented and type-safe. - -The following example declares and uses a delegate type named `Function`. - -[!code-csharp[DelegateExample](../../../samples/snippets/csharp/tour/delegates/Program.cs#L3-L37)] - -An instance of the `Function` delegate type can reference any method that takes a `double` argument and returns a `double` value. The `Apply` method applies a given Function to the elements of a `double[]`, returning a `double[]` with the results. In the `Main` method, `Apply` is used to apply three different functions to a `double[]`. - -A delegate can reference either a static method (such as `Square` or `Math.Sin` in the previous example) or an instance method (such as `m.Multiply` in the previous example). A delegate that references an instance method also references a particular object, and when the instance method is invoked through the delegate, that object becomes `this` in the invocation. - -Delegates can also be created using anonymous functions, which are "inline methods" that are created when declared. Anonymous functions can see the local variables of the surrounding methods. The following example doesn't create a class: - -[!code-csharp[LambdaExample](../../../samples/snippets/csharp/tour/delegates/Program.cs#L44-L44)] - -A delegate doesn't know or care about the class of the method it references; all that matters is that the referenced method has the same parameters and return type as the delegate. - ->[!div class="step-by-step"] ->[Previous](interfaces.md) ->[Next](attributes.md) diff --git a/docs/csharp/tour-of-csharp/expressions.md b/docs/csharp/tour-of-csharp/expressions.md deleted file mode 100644 index 542d72a7c0df4..0000000000000 --- a/docs/csharp/tour-of-csharp/expressions.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: C# Expressions - A tour of the C# language -description: Expressions, operands, and operators are building blocks of the C# language -ms.date: 02/27/2020 -ms.assetid: 20d5eb10-7381-47b9-ad90-f1cc895aa27e ---- -# Expressions - -*Expressions* are constructed from *operands* and *operators*. The operators of an expression indicate which operations to apply to the operands. Examples of operators include `+`, `-`, `*`, `/`, and `new`. Examples of operands include literals, fields, local variables, and expressions. - -When an expression contains multiple operators, the *precedence* of the operators controls the order in which the individual operators are evaluated. For example, the expression `x + y * z` is evaluated as `x + (y * z)` because the `*` operator has higher precedence than the `+` operator. - -When an operand occurs between two operators with the same precedence, the *associativity* of the operators controls the order in which the operations are performed: - -* Except for the assignment and null-coalescing operators, all binary operators are *left-associative*, meaning that operations are performed from left to right. For example, `x + y + z` is evaluated as `(x + y) + z`. -* The assignment operators, the null-coalescing `??` and `??=` operators, and the conditional operator `?:` are *right-associative*, meaning that operations are performed from right to left. For example, `x = y = z` is evaluated as `x = (y = z)`. - -Precedence and associativity can be controlled using parentheses. For example, `x + y * z` first multiplies `y` by `z` and then adds the result to `x`, but `(x + y) * z` first adds `x` and `y` and then multiplies the result by `z`. - -Most operators can be [*overloaded*](../language-reference/operators/operator-overloading.md). Operator overloading permits user-defined operator implementations to be specified for operations where one or both of the operands are of a user-defined class or struct type. - -C# provides a number of operators to perform [arithmetic](../language-reference/operators/arithmetic-operators.md), [logical](../language-reference/operators/boolean-logical-operators.md), [bitwise and shift](../language-reference/operators/bitwise-and-shift-operators.md) operations and [equality](../language-reference/operators/equality-operators.md) and [order](../language-reference/operators/comparison-operators.md) comparisons. - -For the complete list of C# operators ordered by precedence level, see [C# operators](../language-reference/operators/index.md). - -> [!div class="step-by-step"] -> [Previous](types-and-variables.md) -> [Next](statements.md) diff --git a/docs/csharp/tour-of-csharp/features.md b/docs/csharp/tour-of-csharp/features.md new file mode 100644 index 0000000000000..1dbbd95224a13 --- /dev/null +++ b/docs/csharp/tour-of-csharp/features.md @@ -0,0 +1,129 @@ +--- +title: A Tour of C# - C# Guide +description: New to C#? Learn the basics of the language. +ms.date: 08/03/2020 +--- +# Major features + +## Arrays, collections and LINQ + +C# and .NET provide many different collection types. Arrays have syntax defined by the language. General collection types are listed in the namespace. Specialized collections include for accessing continuous memory on the stack frame, and for accessing continuous memory on the managed heap. All collections, including arrays, and share a unifying principle for iteration. You use the interface. This unifying principle means that any of the collection types can be used with LINQ queries or other algorithms. You write methods using and those algorithms work with any collection. + +### Arrays + +An ***array*** is a data structure that contains a number of variables that are accessed through computed indices. The variables contained in an array, also called the ***elements*** of the array, are all of the same type, and this type is called the ***element type*** of the array. + +Array types are reference types, and the declaration of an array variable simply sets aside space for a reference to an array instance. Actual array instances are created dynamically at runtime using the new operator. The new operation specifies the ***length*** of the new array instance, which is then fixed for the lifetime of the instance. The indices of the elements of an array range from `0` to `Length - 1`. The `new` operator automatically initializes the elements of an array to their default value, which, for example, is zero for all numeric types and `null` for all reference types. + +The following example creates an array of `int` elements, initializes the array, and prints out the contents of the array. + +:::code language="csharp" source="./Snippets/arrays/Program.cs" id="ArraysSample"::: + +This example creates and operates on a ***single-dimensional array***. C# also supports ***multi-dimensional arrays***. The number of dimensions of an array type, also known as the ***rank*** of the array type, is one plus the number of commas written between the square brackets of the array type. The following example allocates a single-dimensional, a two-dimensional, and a three-dimensional array, respectively. + +:::code language="csharp" source="./Snippets/arrays/Program.cs" id="DeclareArrays"::: + +The `a1` array contains 10 elements, the `a2` array contains 50 (10 × 5) elements, and the `a3` array contains 100 (10 × 5 × 2) elements. +The element type of an array can be any type, including an array type. An array with elements of an array type is sometimes called a ***jagged array*** because the lengths of the element arrays don't all have to be the same. The following example allocates an array of arrays of `int`: + +:::code language="csharp" source="./Snippets/arrays/Program.cs" id="ArrayOfArrays"::: + +The first line creates an array with three elements, each of type `int[]` and each with an initial value of `null`. The subsequent lines then initialize the three elements with references to individual array instances of varying lengths. + +The new operator permits the initial values of the array elements to be specified using an ***array initializer***, which is a list of expressions written between the delimiters `{` and `}`. The following example allocates and initializes an `int[]` with three elements. + +:::code language="csharp" source="./Snippets/arrays/Program.cs" id="SnippetInitialize"::: + +The length of the array is inferred from the number of expressions between { and }. Local variable and field declarations can be shortened further such that the array type does not have to be restated. + +:::code language="csharp" source="./Snippets/arrays/Program.cs" id="InitializeShortened"::: + +Both of the previous examples are equivalent to the following code: + +:::code language="csharp" source="./Snippets/arrays/Program.cs" id="InitializeGenerated"::: + +The `foreach` statement can be used to enumerate the elements of any collection. The following code enumerates the array from the preceding example: + +:::code language="csharp" source="./Snippets/arrays/Program.cs" id="EnumerateArray"::: + +The `foreach` statement uses the interface, so can work with any collection. + +## string interpolation + +C# ***string interpolation*** enables you to format strings by define expressions whose results are placed in a format string. For example, the following example prints the temperature on a given day from a set of weather data: + +```csharp +Console.WriteLine($"The low and high temperature on {weatherData.Date:MM-DD-YYYY} was {weatherData.LowTemp} and {weatherData.HighTemp}"); +``` + +An interpolated string is declared using the `$` token. String interpolation evaluates the expressions between `{` and `}`, then converts the result to a `string`, and replaces the text between the brackets with the string result of the expression. The `:` in the first expression, `{weatherData.Data:MM-DD-YYYY}` specifies the *format string*. In the preceding example, it specifies that the date should be printed in "MM-DD-YYYY" format. + +## Pattern Matching + +The C# language provides ***pattern matching*** expressions to query the state of an object and execute code based on that state. You can inspect types and the values of properties and fields to determine which action to take. The `switch` expression is the primary expresion for pattern matching. + +## Delegates and lambda expressions + +A ***delegate type*** represents references to methods with a particular parameter list and return type. Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters. Delegates are similar to the concept of function pointers found in some other languages. Unlike function pointers, delegates are object-oriented and type-safe. + +The following example declares and uses a delegate type named `Function`. + +:::code language="csharp" source="./Snippets/delegates/Program.cs" id="DelegateExample"::: + +An instance of the `Function` delegate type can reference any method that takes a `double` argument and returns a `double` value. The `Apply` method applies a given Function to the elements of a `double[]`, returning a `double[]` with the results. In the `Main` method, `Apply` is used to apply three different functions to a `double[]`. + +A delegate can reference either a static method (such as `Square` or `Math.Sin` in the previous example) or an instance method (such as `m.Multiply` in the previous example). A delegate that references an instance method also references a particular object, and when the instance method is invoked through the delegate, that object becomes `this` in the invocation. + +Delegates can also be created using anonymous functions, which are "inline methods" that are created when declared. Anonymous functions can see the local variables of the surrounding methods. The following example doesn't create a class: + +:::code language="csharp" source="./Snippets/delegates/Program.cs" id="UseDelegate"::: + +A delegate doesn't know or care about the class of the method it references; all that matters is that the referenced method has the same parameters and return type as the delegate. + +## async / await + +C# supports asynchronous programs with two keywords: `async` and `await`. You add the `async` modifier to a method declaration to declare the the method is asynchronous. The `aawit` operator tells the compiler that to asynchronously await for a result to finish. Control is returned to the caller, and the method returns a structure that manages the state of the asynchronous work. The structure is typically a , but can be any type that supports the awaiter pattern. This enables you to write code that reads as its synchronous counterpart, but executes asynchronously. For example, the following code downloads the home page for [Microsoft docs](https://docs.microsoft.com): + +```csharp +public async Task RetrieveDocsHomePage() +{ + var client = new HttpClient(); + byte[] content = await client.GetByteArrayAsync("https://docs.microsoft.com/en-us/"); + + Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: Finished downloading."); + return content.Length; +} +``` + +This small sample shows the major features for asynchronous programming: + +- The method declaration includes the `async` modifier. +- The body of the method `await`s the return of the `GetByteArrayAsync` method. +- The type specified in the `return` statement matches the type argument in the `TaskL` declaration for the method. (A method that returns a `Task` would use `return` statements without any argument). + +## Attributes + +Types, members, and other entities in a C# program support modifiers that control certain aspects of their behavior. For example, the accessibility of a method is controlled using the `public`, `protected`, `internal`, and `private` modifiers. C# generalizes this capability such that user-defined types of declarative information can be attached to program entities and retrieved at run-time. Programs specify this additional declarative information by defining and using ***attributes***. + +The following example declares a `HelpAttribute` attribute that can be placed on program entities to provide links to their associated documentation. + +:::code language="csharp" source="./Snippets/attributes/Program.cs" id="DefineAttribute"::: + +All attribute classes derive from the base class provided by the standard library. Attributes can be applied by giving their name, along with any arguments, inside square brackets just before the associated declaration. If an attribute’s name ends in `Attribute`, that part of the name can be omitted when the attribute is referenced. For example, the `HelpAttribute` can be used as follows. + +:::code language="csharp" source="./Snippets/attributes/Program.cs" id="UseAttributes"::: + +This example attaches a `HelpAttribute` to the `Widget` class. It adds another `HelpAttribute` to the `Display` method in the class. The public constructors of an attribute class control the information that must be provided when the attribute is attached to a program entity. Additional information can be provided by referencing public read-write properties of the attribute class (such as the reference to the `Topic` property previously). + +The metadata defined by attributes can be read and manipulated at runtime using reflection. When a particular attribute is requested using this technique, the constructor for the attribute class is invoked with the information provided in the program source, and the resulting attribute instance is returned. If additional information was provided through properties, those properties are set to the given values before the attribute instance is returned. + +The following code sample demonstrates how to get the `HelpAttribute` instances associated to the `Widget` class and its `Display` method. + +:::code language="csharp" source="./Snippets/attributes/Program.cs" id="SnippetReadAttributes"::: + +## Learn more + +You can explore more about C# by trying one of our [tutorials](../tutorials/index.md). + +>[!div class="step-by-step"] +>[Previous](program-building-blocks.md) diff --git a/docs/csharp/tour-of-csharp/index.md b/docs/csharp/tour-of-csharp/index.md index fb918d10608bd..528ffe0388430 100644 --- a/docs/csharp/tour-of-csharp/index.md +++ b/docs/csharp/tour-of-csharp/index.md @@ -1,75 +1,129 @@ --- title: A Tour of C# - C# Guide description: New to C#? Learn the basics of the language. -ms.date: 02/26/2020 +ms.date: 08/03/2020 --- # A tour of the C# language -C# (pronounced "See Sharp") is a modern, object-oriented, and type-safe programming language. C# has its roots in the C family of languages and will be immediately familiar to C, C++, Java, and JavaScript programmers. +C# (pronounced "See Sharp") is a modern, object-oriented, and type-safe programming language. C# has its roots in the C family of languages and will be immediately familiar to C, C++, Java, and JavaScript programmers. This tour provides an overview of the major components of the language in C# 8 and earlier. If you want to explore the language through interactive examples, try the [introduction to C#](../tutorials/intro-to-csharp/index.md) tutorials. -This tour provides an overview of the major components of the language in C# 8 and earlier. If you want to explore the language through interactive examples, try the [introduction to C#](../tutorials/intro-to-csharp/index.md) tutorials. +C# is an object-oriented, ***component-oriented*** programming. C# provides language constructs to support directly these concepts, making C# a natural language in which to create and use software components. Since its inception, C# has added features to support new workloads and emerging software design practices. -C# is an object-oriented language, but C# further includes support for ***component-oriented*** programming. Contemporary software design increasingly relies on software components in the form of self-contained and self-describing packages of functionality. Key to such components is that they present a programming model with properties, methods, and events. They have attributes that provide declarative information about the component. They incorporate their own documentation. C# provides language constructs to support directly these concepts, making C# a natural language in which to create and use software components. +Several C# features aid in the construction of robust and durable applications. ***Garbage collection*** automatically reclaims memory occupied by unreachable unused objects. ***Exception handling*** provides a structured and extensible approach to error detection and recovery. ***Lambda expressions*** suppport functional programming techniques. ***Query syntax*** creates a common pattern for working with data from any source. Language support for ***asynchronous operations*** provides syntax for building distributed systems. ***Pattern matching*** provides syntax to easily separate data from algorithms in modern distributed systems. C# has a ***unified type system***. All C# types, including primitive types such as `int` and `double`, inherit from a single root `object` type. Thus, all types share a set of common operations, and values of any type can be stored, transported, and operated upon in a consistent manner. Furthermore, C# supports both user-defined reference types and value types, allowing dynamic allocation of objects as well as in-line storage of lightweight structures. -Several C# features aid in the construction of robust and durable applications. ***Garbage collection*** automatically reclaims memory occupied by unreachable unused objects. ***Exception handling*** provides a structured and extensible approach to error detection and recovery. The ***type-safe*** design of the language makes it impossible to read from uninitialized variables, to index arrays beyond their bounds, or to perform unchecked type casts. +To ensure that C# programs and libraries can evolve over time in a compatible manner, much emphasis has been placed on ***versioning*** in C#'s design. Aspects of C#'s design that were directly influenced by versioning considerations include the separate `virtual` and `override` modifiers, the rules for method overload resolution, and support for explicit interface member declarations. -C# has a ***unified type system***. All C# types, including primitive types such as `int` and `double`, inherit from a single root `object` type. Thus, all types share a set of common operations, and values of any type can be stored, transported, and operated upon in a consistent manner. Furthermore, C# supports both user-defined reference types and value types, allowing dynamic allocation of objects as well as in-line storage of lightweight structures. +## Hello world -To ensure that C# programs and libraries can evolve over time in a compatible manner, much emphasis has been placed on ***versioning*** in C#'s design. Many programming languages pay little attention to this issue. As a result, programs written in those other languages break more often than necessary when newer versions of dependent libraries are introduced. Aspects of C#'s design that were directly influenced by versioning considerations include the separate `virtual` and `override` modifiers, the rules for method overload resolution, and support for explicit interface member declarations. +The "Hello, World" program is traditionally used to introduce a programming language. Here it is in C#: -In more recent versions, C# has embraced other programming paradigms. C# has included features that support functional programming techniques like lambda expressions. Other new features support separating data and algorithms, like pattern matching. +:::code language="csharp" interactive="try-dotnet" source="./Snippets/hello/Program.cs"::: -## Hello world +The "Hello, World" program starts with a `using` directive that references the `System` namespace. Namespaces provide a hierarchical means of organizing C# programs and libraries. Namespaces contain types and other namespaces—for example, the `System` namespace contains a number of types, such as the `Console` class referenced in the program, and a number of other namespaces, such as `IO` and `Collections`. A `using` directive that references a given namespace enables unqualified use of the types that are members of that namespace. Because of the `using` directive, the program can use `Console.WriteLine` as shorthand for `System.Console.WriteLine`. -The "Hello, World" program is traditionally used to introduce a programming language. Here it is in C#: +The `Hello` class declared by the "Hello, World" program has a single member, the method named `Main`. The `Main` method is declared with the `static` modifier. While instance methods can reference a particular enclosing object instance using the keyword `this`, static methods operate without reference to a particular object. By convention, a static method named `Main` serves as the entry point of a program. -[!code-csharp[Hello World](~/samples/snippets/csharp/tour/hello/Program.cs)] +The output of the program is produced by the `WriteLine` method of the `Console` class in the `System` namespace. This class is provided by the standard class libraries, which, by default, are automatically referenced by the compiler. -C# source files typically have the file extension `.cs`. To create this program, first download and install the [.NET Core SDK](https://dotnet.microsoft.com/download). Then, execute the command `dotnet new console -o hello` to create a new program and a build script. The program and build script are in the files `Program.cs` and `hello.csproj`, respectively. You build and run the application with the `run` commands: +## Types and variables -```dotnetcli -cd hello -dotnet run -``` +There are two kinds of types in C#: *value types* and *reference types*. Variables of value types directly contain their data whereas variables of reference types store references to their data, the latter being known as objects. With reference types, it's possible for two variables to reference the same object and thus possible for operations on one variable to affect the object referenced by the other variable. With value types, the variables each have their own copy of the data, and it isn't possible for operations on one to affect the other (except for `ref` and `out` parameter variables). -The program produces the following output: +C#'s value types are further divided into *simple types*, *enum types*, *struct types*, and *nullable value types*. C#'s reference types are further divided into *class types*, *interface types*, *array types*, and *delegate types*. -```dotnetcli -Hello, World! -``` +The following outline provides an overview of C#'s type system. -The "Hello, World" program starts with a `using` directive that references the `System` namespace. Namespaces provide a hierarchical means of organizing C# programs and libraries. Namespaces contain types and other namespaces—for example, the `System` namespace contains a number of types, such as the `Console` class referenced in the program, and a number of other namespaces, such as `IO` and `Collections`. A `using` directive that references a given namespace enables unqualified use of the types that are members of that namespace. Because of the `using` directive, the program can use `Console.WriteLine` as shorthand for `System.Console.WriteLine`. +- [Value types](../language-reference/builtin-types/value-types.md) + - [Simple types](../language-reference/builtin-types/value-types.md#built-in-value-types) + - [Signed integral](../language-reference/builtin-types/integral-numeric-types.md): `sbyte`, `short`, `int`, `long` + - [Unsigned integral](../language-reference/builtin-types/integral-numeric-types.md): `byte`, `ushort`, `uint`, `ulong` + - Unicode characters: `char`, which represents a UTF-16 code unit + - [IEEE binary floating-point](../language-reference/builtin-types/floating-point-numeric-types.md): `float`, `double` + - [High-precision decimal floating-point](../language-reference/builtin-types/floating-point-numeric-types.md): `decimal` + - Boolean: `bool`, which represents Boolean values—values that are either `true` or `false` + - [Enum types](../language-reference/builtin-types/enum.md) + - User-defined types of the form `enum E {...}`. An `enum` type is a distinct type with named constants. Every `enum` type has an underlying type, which must be one of the eight integral types. The set of values of an `enum` type is the same as the set of values of the underlying type. + - [Struct types](../language-reference/builtin-types/struct.md) + - User-defined types of the form `struct S {...}` + - [Nullable value types](../language-reference/builtin-types/nullable-value-types.md) + - Extensions of all other value types with a `null` value + - [Tuple value types](../tuples.md) + - User-defined types of the form `(T1, T2, ...)` +- [Reference types](../language-reference/keywords/reference-types.md) + - [Class types](../language-reference/keywords/class.md) + - Ultimate base class of all other types: `object` + - Unicode strings: `string`, which represents a sequence of UTF-16 code units + - User-defined types of the form `class C {...}` + - [Interface types](../language-reference/keywords/interface.md) + - User-defined types of the form `interface I {...}` + - [Array types](../programming-guide/arrays/index.md) + - Single- and multi-dimensional, for example, `int[]` and `int[,]` + - [Delegate types](../language-reference/keywords/delegate.md) + - User-defined types of the form `delegate int D(...)` -The `Hello` class declared by the "Hello, World" program has a single member, the method named `Main`. The `Main` method is declared with the static modifier. While instance methods can reference a particular enclosing object instance using the keyword `this`, static methods operate without reference to a particular object. By convention, a static method named `Main` serves as the entry point of a program. +C# programs use *type declarations* to create new types. A type declaration specifies the name and the members of the new type. Five of C#'s categories of types are user-definable: class types, struct types, interface types, enum types, and delegate types. -The output of the program is produced by the `WriteLine` method of the `Console` class in the `System` namespace. This class is provided by the standard class libraries, which, by default, are automatically referenced by the compiler. +- A `class` type defines a data structure that contains data members (fields) and function members (methods, properties, and others). Class types support single inheritance and polymorphism, mechanisms whereby derived classes can extend and specialize base classes. +- A `struct` type is similar to a class type in that it represents a structure with data members and function members. However, unlike classes, structs are value types and don't typically require heap allocation. Struct types don't support user-specified inheritance, and all struct types implicitly inherit from type `object`. +- An `interface` type defines a contract as a named set of public members. A `class` or `struct` that implements an `interface` must provide implementations of the interface's members. An `interface` may inherit from multiple base interfaces, and a `class` or `struct` may implement multiple interfaces. +- A `delegate` type represents references to methods with a particular parameter list and return type. Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters. Delegates are analogous to function types provided by functional languages. They're also similar to the concept of function pointers found in some other languages. Unlike function pointers, delegates are object-oriented and type-safe. + +The `class`, `struct`, `interface`, and `delegate` types all support generics, whereby they can be parameterized with other types. + +C# supports single- and multi-dimensional arrays of any type. Unlike the types listed above, array types don't have to be declared before they can be used. Instead, array types are constructed by following a type name with square brackets. For example, `int[]` is a single-dimensional array of `int`, `int[,]` is a two-dimensional array of `int`, and `int[][]` is a single-dimensional array of single-dimensional array of `int`. + +Nullable value types also don't have to be declared before they can be used. For each non-nullable value type `T`, there is a corresponding nullable value type `T?`, which can hold an additional value, `null`. For instance, `int?` is a type that can hold any 32-bit integer or the value `null`. + +C#'s type system is unified such that a value of any type can be treated as an `object`. Every type in C# directly or indirectly derives from the `object` class type, and `object` is the ultimate base class of all types. Values of reference types are treated as objects simply by viewing the values as type `object`. Values of value types are treated as objects by performing *boxing* and *unboxing operations*. In the following example, an `int` value is converted to `object` and back again to `int`. + +:::code language="csharp" interactive="try-dotnet-method" source="./Snippets/types-and-variables/Program.cs" id="boxing" ::: + +When a value of a value type is assigned to an `object` reference, a "box" is allocated to hold the value. That box is an instance of a reference type, and the value is copied into that box. Conversely, when an `object` reference is cast to a value type, a check is made that the referenced `object` is a box of the correct value type. If the check succeeds, the value in the box is copied to the value type. + +C#'s unified type system effectively means that value types are treated as `object` references "on demand." Because of the unification, general-purpose libraries that use type `object` can be used with all types that derive from `object`, including both reference types and value types. + +There are several kinds of *variables* in C#, including fields, array elements, local variables, and parameters. Variables represent storage locations, and every variable has a type that determines what values can be stored in the variable, as shown below. + +- Non-nullable value type + - A value of that exact type +- Nullable value type + - A `null` value or a value of that exact type +- object + - A `null` reference, a reference to an object of any reference type, or a reference to a boxed value of any value type +- Class type + - A `null` reference, a reference to an instance of that class type, or a reference to an instance of a class derived from that class type +- Interface type + - A `null` reference, a reference to an instance of a class type that implements that interface type, or a reference to a boxed value of a value type that implements that interface type +- Array type + - A `null` reference, a reference to an instance of that array type, or a reference to an instance of a compatible array type +- Delegate type + - A `null` reference or a reference to an instance of a compatible delegate type + +## Program structure + +The key organizational concepts in C# are ***programs***, ***namespaces***, ***types***, ***members***, and ***assemblies***. Programs declare types, which contain members and can be organized into namespaces. Classes, structs, and interfaces are examples of types. Fields, methods, properties, and events are examples of members. When C# programs are compiled, they're physically packaged into assemblies. Assemblies typically have the file extension `.exe` or `.dll`, depending on whether they implement ***applications*** or ***libraries***, respectively. + +As a small example, consider an assembly that contains the following code: + +:::code language="csharp" source="./Snippets/program-structure/Program.cs" id="SnippetStackExample"::: + +The fully qualified name of this class is `Acme.Collections.Stack`. The class contains several members: a field named `top`, two methods named `Push` and `Pop`, and a nested class named `Entry`. The `Entry` class further contains three members: a field named `next`, a field named `data`, and a constructor. The `Stack` is a *generic* class. It has one type parameter, `T` that is replaced with a concrete type when it's used. -## Elements of the C# language - -There's a lot more to learn about C#. The following topics provide an overview of the elements of the C# language. These overviews provide basic information about all elements of the language and give you the information necessary to dive deeper: - -- [Program Structure](program-structure.md) - - Learn the key organizational concepts in the C# language: ***programs***, ***namespaces***, ***types***, ***members***, and ***assemblies***. -- [Types and Variables](types-and-variables.md) - - Learn about ***value types***, ***reference types***, and ***variables*** in the C# language. -- [Expressions](expressions.md) - - ***Expressions*** are constructed from ***operands*** and ***operators***. Expressions produce a value. -- [Statements](statements.md) - - You use ***statements*** to express the actions of a program. -- [Classes and objects](classes-and-objects.md) - - ***Classes*** are the most fundamental of C#'s types. ***Objects*** are instances of a class. Classes are built using ***members***, which are also covered in this topic. -- [Arrays](arrays.md) - - An ***array*** is a data structure that contains a number of variables that are accessed through computed indices. -- [Interfaces](interfaces.md) - - An ***interface*** defines a contract that can be implemented by classes and structs. An interface can contain methods, properties, events, and indexers. An interface doesn't provide implementations of the members it defines—it merely specifies the members that must be supplied by classes or structs that implement the interface. -- [Delegates](delegates.md) - - A ***delegate type*** represents references to methods with a particular parameter list and return type. Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters. Delegates are similar to the concept of function pointers found in some other languages, but unlike function pointers, delegates are object-oriented and type-safe. -- [Attributes](attributes.md) - - ***Attributes*** enable programs to specify additional declarative information about types, members, and other entities. - > [!NOTE] -> These articles apply to C# 7.0 and later. Some features may not be available in earlier versions. +> A *stack* is a "first in - last out" (FILO) collection. New elements are added to the top of the stack. When an element is removed, it is removed from the top of the stack. + +Assemblies contain executable code in the form of Intermediate Language (IL) instructions, and symbolic information in the form of metadata. Before it's executed, the Just-In-Time (JIT) compiler of .NET Common Language Runtime converts the IL code in an assembly to processor-specific code. + +Because an assembly is a self-describing unit of functionality containing both code and metadata, there's no need for `#include` directives and header files in C#. The public types and members contained in a particular assembly are made available in a C# program simply by referencing that assembly when compiling the program. For example, this program uses the `Acme.Collections.Stack` class from the `acme.dll` assembly: + +:::code language="csharp" source="./Snippets/program-structure/Program.cs" id="SnippetStackUsage"::: + +To compile this program, you would need to *reference* the assesmbly containing the stack class defined in the earlier example. + +C# programs can be stored in several source files. When a C# program is compiled, all of the source files are processed together, and the source files can freely reference each other. Conceptually, it's as if all the source files were concatenated into one large file before being processed. Forward declarations are never needed in C# because, with few exceptions, declaration order is insignificant. C# doesn't limit a source file to declaring only one public type nor does it require the name of the source file to match a type declared in the source file. + +Further articles in this tour explain these organizational blocks. -> [!div class="step-by-step"] -> [Next](program-structure.md) +>[!div class="step-by-step"] +>[Next](types.md) diff --git a/docs/csharp/tour-of-csharp/interfaces.md b/docs/csharp/tour-of-csharp/interfaces.md deleted file mode 100644 index b5f1eba9dcd45..0000000000000 --- a/docs/csharp/tour-of-csharp/interfaces.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: C# Interfaces - A tour of the C# language -description: Interfaces define contracts implemented by types in C# -ms.date: 02/27/2020 -ms.assetid: a9bf82f4-efd1-4216-bd34-4ef0fa48c968 ---- - -# Interfaces - -An ***interface*** defines a contract that can be implemented by classes and structs. An interface can contain methods, properties, events, and indexers. An interface doesn't provide implementations of the members it defines—it merely specifies the members that must be supplied by classes or structs that implement the interface. - -Interfaces may employ ***multiple inheritance***. In the following example, the interface `IComboBox` inherits from both `ITextBox` and `IListBox`. - -[!code-csharp[InterfacesOne](../../../samples/snippets/csharp/tour/interfaces/Program.cs#L5-L17)] - -Classes and structs can implement multiple interfaces. In the following example, the class `EditBox` implements both `IControl` and `IDataBound`. - -[!code-csharp[InterfacesTwo](../../../samples/snippets/csharp/tour/interfaces/Program.cs#L19-L27)] - -When a class or struct implements a particular interface, instances of that class or struct can be implicitly converted to that interface type. For example - -[!code-csharp[InterfacesThree](../../../samples/snippets/csharp/tour/interfaces/Program.cs#L33-L35)] - -In cases where an instance isn't statically known to implement a particular interface, dynamic type casts can be used. For example, the following statements use dynamic type casts to obtain an object’s `IControl` and `IDataBound` interface implementations. Because the run-time actual type of the object is `EditBox`, the casts succeed. - -[!code-csharp[InterfacesFour](../../../samples/snippets/csharp/tour/interfaces/Program.cs#L40-L42)] - -In the previous `EditBox` class, the `Paint` method from the `IControl` interface and the `Bind` method from the `IDataBound` interface are implemented using public members. C# also supports explicit ***interface member implementations***, enabling the class or struct to avoid making the members public. An explicit interface member implementation is written using the fully qualified interface member name. For example, the `EditBox` class could implement the `IControl.Paint` and `IDataBound.Bind` methods using explicit interface member implementations as follows. - -[!code-csharp[InterfacesFive](../../../samples/snippets/csharp/tour/interfaces/Program.cs#L60-L64)] - -Explicit interface members can only be accessed via the interface type. For example, the implementation of `IControl.Paint` provided by the previous EditBox class can only be invoked by first converting the `EditBox` reference to the `IControl` interface type. - -[!code-csharp[InterfacesFive](../../../samples/snippets/csharp/tour/interfaces/Program.cs#L71-L74)] - ->[!div class="step-by-step"] ->[Previous](arrays.md) ->[Next](delegates.md) diff --git a/docs/csharp/tour-of-csharp/classes-and-objects.md b/docs/csharp/tour-of-csharp/program-building-blocks.md similarity index 67% rename from docs/csharp/tour-of-csharp/classes-and-objects.md rename to docs/csharp/tour-of-csharp/program-building-blocks.md index 072b3fdbd0699..a6acf8d2bb7c0 100644 --- a/docs/csharp/tour-of-csharp/classes-and-objects.md +++ b/docs/csharp/tour-of-csharp/program-building-blocks.md @@ -1,94 +1,39 @@ --- -title: Classes and Objects in C# - A tour of the C# Language -description: New to C#? Read this overview of classes, objects, and inheritance -ms.date: 02/27/2020 -ms.assetid: 63a89bde-0f05-4bc4-b0cd-4f693854f0cd +title: "The building blocks of of C# programs: Learn about members, expressions and statements." +description: Types contain members you write. Those members are built from statements and expressions. +ms.date: 08/03/2020 --- +# Program Building blocks -# Classes and objects - -*Classes* are the most fundamental of C#’s types. A class is a data structure that combines state (fields) and actions (methods and other function members) in a single unit. A class provides a definition for dynamically created *instances* of the class, also known as *objects*. Classes support *inheritance* and *polymorphism*, mechanisms whereby *derived classes* can extend and specialize *base classes*. - -New classes are created using class declarations. A class declaration starts with a header that specifies the attributes and modifiers of the class, the name of the class, the base class (if given), and the interfaces implemented by the class. The header is followed by the class body, which consists of a list of member declarations written between the delimiters `{` and `}`. - -The following code shows a declaration of a simple class named `Point`: - -[!code-csharp[PointClass](~/samples/snippets/csharp/tour/classes-and-objects/Point.cs#L3-L11)] - -Instances of classes are created using the `new` operator, which allocates memory for a new instance, invokes a constructor to initialize the instance, and returns a reference to the instance. The following statements create two Point objects and store references to those objects in two variables: - -[!code-csharp[PointExample](~/samples/snippets/csharp/tour/classes-and-objects/Program.cs#L9-L10)] - -The memory occupied by an object is automatically reclaimed when the object is no longer reachable. It's neither necessary nor possible to explicitly deallocate objects in C#. +The types described in the previous article are built using these building blocks: ***members***, ***expressions*** and ***statements***. ## Members -The members of a class are either static members or instance members. Static members belong to classes, and instance members belong to objects (instances of classes). +The members of a `class` are either ***static members*** or ***instance members***. Static members belong to classes, and instance members belong to objects (instances of classes). The following list provides an overview of the kinds of members a class can contain. -- Constants - - Constant values associated with the class -- Fields - - Variables of the class -- Methods - - Computations and actions that can be performed by the class -- Properties - - Actions associated with reading and writing named properties of the class -- Indexers - - Actions associated with indexing instances of the class like an array -- Events - - Notifications that can be generated by the class -- Operators - - Conversions and expression operators supported by the class -- Constructors - - Actions required to initialize instances of the class or the class itself -- Finalizers - - Actions to perform before instances of the class are permanently discarded -- Types - - Nested types declared by the class +- **Constants**: Constant values associated with the class +- **Fields**: of the class +- **Methods**: and actions that can be performed by the class +- **Properties**: Actions associated with reading and writing named properties of the class +- **Indexers**: Actions associated with indexing instances of the class like an array +- **Events**: Notifications that can be generated by the class +- **Operators**: Conversions and expression operators supported by the class +- **Constructors**: Actions required to initialize instances of the class or the class itself +- **Finalizers**: Actions to perform before instances of the class are permanently discarded +- **Types**: Nested types declared by the class ## Accessibility Each member of a class has an associated accessibility, which controls the regions of program text that can access the member. There are six possible forms of accessibility. The access modifiers are summarized below. -- `public` - - Access isn't limited. -- `protected` - - Access is limited to this class or classes derived from this class. -- `internal` - - Access is limited to the current assembly (.exe, .dll, and so on.). -- `protected internal` - - Access is limited to the containing class, classes derived from the containing class, or classes within the same assembly. -- `private` - - Access is limited to this class. -- `private protected` - - Access is limited to the containing class or classes derived from the containing type within the same assembly. - -## Type parameters - -A class definition may specify a set of type parameters by following the class name with angle brackets enclosing a list of type parameter names. The type parameters can then be used in the body of the class declarations to define the members of the class. In the following example, the type parameters of `Pair` are `TFirst` and `TSecond`: - -[!code-csharp[Pair](~/samples/snippets/csharp/tour/classes-and-objects/Pair.cs#L3-L7)] - -A class type that is declared to take type parameters is called a *generic class type*. Struct, interface, and delegate types can also be generic. -When the generic class is used, type arguments must be provided for each of the type parameters: - -[!code-csharp[PairExample](~/samples/snippets/csharp/tour/classes-and-objects/Program.cs#L15-L17)] - -A generic type with type arguments provided, like `Pair` above, is called a *constructed type*. - -## Base classes - -A class declaration may specify a base class by following the class name and type parameters with a colon and the name of the base class. Omitting a base class specification is the same as deriving from type `object`. In the following example, the base class of `Point3D` is `Point`, and the base class of `Point` is `object`: - -[!code-csharp[Point3DClass](~/samples/snippets/csharp/tour/classes-and-objects/Point.cs#L3-L20)] - -A class inherits the members of its base class. Inheritance means that a class implicitly contains all members of its base class, except for the instance and static constructors, and the finalizers of the base class. A derived class can add new members to those members it inherits, but it can't remove the definition of an inherited member. In the previous example, `Point3D` inherits the `x` and `y` fields from `Point`, and every `Point3D` instance contains three fields, `x`, `y`, and `z`. - -An implicit conversion exists from a class type to any of its base class types. A variable of a class type can reference an instance of that class or an instance of any derived class. For example, given the previous class declarations, a variable of type `Point` can reference either a `Point` or a `Point3D`: - -[!code-csharp[Point3DExample](~/samples/snippets/csharp/tour/classes-and-objects/Program.cs#L22-L23)] +- `public`: Access isn't limited. +- `protected`: Access is limited to this class or classes derived from this class. +- `internal`: Access is limited to the current assembly (.exe, .dll, and so on.). +- `protected internal`: Access is limited to the containing class, classes derived from the containing class, or classes within the same assembly. +- `private`: Access is limited to this class. +- `private protected`: Access is limited to the containing class or classes derived from the containing type within the same assembly. ## Fields @@ -100,7 +45,7 @@ A field declared without the static modifier defines an instance field. Every in In the following example, each instance of the `Color` class has a separate copy of the `r`, `g`, and `b` instance fields, but there's only one copy of the `Black`, `White`, `Red`, `Green`, and `Blue` static fields: -[!code-csharp[ColorClass](~/samples/snippets/csharp/tour/classes-and-objects/Color.cs#L3-L17)] +:::code language="csharp" source="./Snippets/classes-and-objects/Color.cs" id="ColorClassDefinition"::: As shown in the previous example, *read-only fields* may be declared with a `readonly` modifier. Assignment to a `readonly` field can only occur as part of the field’s declaration or in a constructor in the same class. @@ -124,23 +69,23 @@ Value parameters can be optional, by specifying a default value so that correspo A *reference parameter* is used for passing arguments by reference. The argument passed for a reference parameter must be a variable with a definite value, and during execution of the method, the reference parameter represents the same storage location as the argument variable. A reference parameter is declared with the `ref` modifier. The following example shows the use of `ref` parameters. -[!code-csharp[swapExample](~/samples/snippets/csharp/tour/classes-and-objects/RefExample.cs#L3-L18)] +:::code language="csharp" source="./Snippets/classes-and-objects/RefExample.cs" id="RefExample"::: An *output parameter* is used for passing arguments by reference. It's similar to a reference parameter, except that it doesn't require that you explicitly assign a value to the caller-provided argument. An output parameter is declared with the `out` modifier. The following example shows the use of `out` parameters using the syntax introduced in C# 7. -[!code-csharp[OutExample](~/samples/snippets/csharp/tour/classes-and-objects/OutExample.cs#L3-L17)] +:::code language="csharp" source="./Snippets/classes-and-objects/OutExample.cs" id="OutExample"::: A *parameter array* permits a variable number of arguments to be passed to a method. A parameter array is declared with the `params` modifier. Only the last parameter of a method can be a parameter array, and the type of a parameter array must be a single-dimensional array type. The Write and WriteLine methods of the class are good examples of parameter array usage. They're declared as follows. -[!code-csharp[ConsoleExample](~/samples/snippets/csharp/tour/classes-and-objects/Program.cs#L78-L83)] +:::code language="csharp" source="./Snippets/classes-and-objects/Program.cs" id="ConsoleExtract"::: Within a method that uses a parameter array, the parameter array behaves exactly like a regular parameter of an array type. However, in an invocation of a method with a parameter array, it's possible to pass either a single argument of the parameter array type or any number of arguments of the element type of the parameter array. In the latter case, an array instance is automatically created and initialized with the given arguments. This example -[!code-csharp[StringFormat](~/samples/snippets/csharp/tour/classes-and-objects/Program.cs#L55-L55)] +:::code language="csharp" source="./Snippets/classes-and-objects/Program.cs" id="UseParamsArgs"::: is equivalent to writing the following. -[!code-csharp[StringFormat2](~/samples/snippets/csharp/tour/classes-and-objects/Program.cs#L30-L35)] +:::code language="csharp" source="./Snippets/classes-and-objects/Program.cs" id="CompilerParams"::: ### Method body and local variables @@ -148,7 +93,7 @@ A method’s body specifies the statements to execute when the method is invoked A method body can declare variables that are specific to the invocation of the method. Such variables are called *local variables*. A local variable declaration specifies a type name, a variable name, and possibly an initial value. The following example declares a local variable `i` with an initial value of zero and a local variable `j` with no initial value. -[!code-csharp[Squares](~/samples/snippets/csharp/tour/classes-and-objects/Squares.cs#L3-L17)] +:::code language="csharp" source="./Snippets/classes-and-objects/Squares.cs" id="SquaresClass"::: C# requires a local variable to be *definitely assigned* before its value can be obtained. For example, if the declaration of the previous `i` didn't include an initial value, the compiler would report an error for the subsequent usages of `i` because `i` wouldn't be definitely assigned at those points in the program. @@ -162,7 +107,7 @@ A method declared without a static modifier is an *instance method*. An instance The following `Entity` class has both static and instance members. -[!code-csharp[Entity](~/samples/snippets/csharp/tour/classes-and-objects/Entity.cs#L16-L36)] +:::code language="csharp" source="./Snippets/classes-and-objects/Entity.cs" id="EntityClass"::: Each `Entity` instance contains a serial number (and presumably some other information that isn't shown here). The `Entity` constructor (which is like an instance method) initializes the new instance with the next available serial number. Because the constructor is an instance member, it's permitted to access both the `serialNo` instance field and the `nextSerialNo` static field. @@ -170,7 +115,7 @@ The `GetNextSerialNo` and `SetNextSerialNo` static methods can access the `nextS The following example shows the use of the Entity class. -[!code-csharp[EntityExample](~/samples/snippets/csharp/tour/classes-and-objects/Entity.cs#L3-L15)] +:::code language="csharp" source="./Snippets/classes-and-objects/Entity.cs" id="UsingEntity"::: The `SetNextSerialNo` and `GetNextSerialNo` static methods are invoked on the class whereas the `GetSerialNo` instance method is invoked on instances of the class. @@ -186,11 +131,11 @@ An *abstract method* is a virtual method with no implementation. An abstract met The following example declares an abstract class, `Expression`, which represents an expression tree node, and three derived classes, `Constant`, `VariableReference`, and `Operation`, which implement expression tree nodes for constants, variable references, and arithmetic operations. (This example is similar to, but not to be confused with the expression tree types). -[!code-csharp[ExpressionClass](~/samples/snippets/csharp/tour/classes-and-objects/Expressions.cs#L3-L61)] +:::code language="csharp" source="./Snippets/classes-and-objects/Expressions.cs" id="WorkingWithExpressions"::: The previous four classes can be used to model arithmetic expressions. For example, using instances of these classes, the expression `x + 3` can be represented as follows. -[!code-csharp[ExpressionExample](~/samples/snippets/csharp/tour/classes-and-objects/Program.cs#L40-L43)] +:::code language="csharp" source="./Snippets/classes-and-objects/Program.cs" id="UseExpressions"::: The `Evaluate` method of an `Expression` instance is invoked to evaluate the given expression and produce a `double` value. The method takes a `Dictionary` argument that contains variable names (as keys of the entries) and values (as values of the entries). Because `Evaluate` is an abstract method, non-abstract classes derived from `Expression` must override `Evaluate`. @@ -198,13 +143,13 @@ A `Constant`'s implementation of `Evaluate` simply returns the stored constant. The following program uses the `Expression` classes to evaluate the expression `x * (y + 2)` for different values of `x` and `y`. -[!code-csharp[ExpressionUsage](~/samples/snippets/csharp/tour/classes-and-objects/Expressions.cs#L66-L89)] +:::code language="csharp" source="./Snippets/classes-and-objects/Expressions.cs" id="UsingExpressions"::: ### Method overloading Method *overloading* permits multiple methods in the same class to have the same name as long as they have unique signatures. When compiling an invocation of an overloaded method, the compiler uses *overload resolution* to determine the specific method to invoke. Overload resolution finds the one method that best matches the arguments or reports an error if no single best match can be found. The following example shows overload resolution in effect. The comment for each invocation in the `UsageExample` method shows which method is invoked. -[!code-csharp[OverloadUsage](~/samples/snippets/csharp/tour/classes-and-objects/Overloading.cs#L3-L41)] +:::code language="csharp" source="./Snippets/classes-and-objects/Overloading.cs" id="Overloading"::: As shown by the example, a particular method can always be selected by explicitly casting the arguments to the exact parameter types and/or explicitly supplying type arguments. @@ -217,7 +162,7 @@ The following example shows a generic class called `MyList`, which implements > [!NOTE] > This example creates a `MyList` class, which is not the same as the .NET standard . It does illustrate the concepts needed for this tour, but is not a replacement for that class. -[!code-csharp[ListClass](~/samples/snippets/csharp/tour/classes-and-objects/ListBasedExamples.cs#L4-L89)] +:::code language="csharp" source="./Snippets/classes-and-objects/ListBasedExamples.cs" id="ListExample"::: ### Constructors @@ -227,7 +172,7 @@ A constructor is declared like a method with no return type and the same name as Instance constructors can be overloaded and can have optional parameters. For example, the `MyList` class declares one instance constructor with a single optional `int` parameter. Instance constructors are invoked using the `new` operator. The following statements allocate two `MyList` instances using the constructor of the `MyList` class with and without the optional argument. -[!code-csharp[ListExample1](~/samples/snippets/csharp/tour/classes-and-objects/ListBasedExamples.cs#L95-L96)] +:::code language="csharp" source="./Snippets/classes-and-objects/ListBasedExamples.cs" id="CreateLists"::: Unlike other members, instance constructors aren't inherited, and a class has no instance constructors other than those constructors actually declared in the class. If no instance constructor is supplied for a class, then an empty one with no parameters is automatically provided. @@ -243,7 +188,7 @@ A set accessor corresponds to a method with a single parameter named value and n The `MyList` class declares two properties, `Count` and `Capacity`, which are read-only and read-write, respectively. The following code is an example of use of these properties: -[!code-csharp[ListExample2](~/samples/snippets/csharp/tour/classes-and-objects/ListBasedExamples.cs#L101-L104)] +:::code language="csharp" source="./Snippets/classes-and-objects/ListBasedExamples.cs" id="AccessProperties"::: Similar to fields and methods, C# supports both instance properties and static properties. Static properties are declared with the static modifier, and instance properties are declared without it. @@ -255,7 +200,7 @@ An *indexer* is a member that enables objects to be indexed in the same way as a The `MyList` class declares a single read-write indexer that takes an `int` parameter. The indexer makes it possible to index `MyList` instances with `int` values. For example: -[!code-csharp[ListExample3](~/samples/snippets/csharp/tour/classes-and-objects/ListBasedExamples.cs#L109-L117)] +:::code language="csharp" source="./Snippets/classes-and-objects/ListBasedExamples.cs" id="ListAddition"::: Indexers can be overloaded, meaning that a class can declare multiple indexers as long as the number or types of their parameters differ. @@ -269,7 +214,7 @@ The `MyList` class declares a single event member called `Changed`, which ind Clients react to events through *event handlers*. Event handlers are attached using the `+=` operator and removed using the `-=` operator. The following example attaches an event handler to the `Changed` event of a `MyList`. -[!code-csharp[EventExample](~/samples/snippets/csharp/tour/classes-and-objects/ListBasedExamples.cs#L132-L148)] +:::code language="csharp" source="./Snippets/classes-and-objects/ListBasedExamples.cs" id="RespondToEvents"::: For advanced scenarios where control of the underlying storage of an event is desired, an event declaration can explicitly provide `add` and `remove` accessors, which are similar to the `set` accessor of a property. @@ -279,7 +224,7 @@ An *operator* is a member that defines the meaning of applying a particular expr The `MyList` class declares two operators, `operator ==` and `operator !=`, and thus gives new meaning to expressions that apply those operators to `MyList` instances. Specifically, the operators define equality of two `MyList` instances as comparing each of the contained objects using their Equals methods. The following example uses the `==` operator to compare two `MyList` instances. -[!code-csharp[OperatorExample](~/samples/snippets/csharp/tour/classes-and-objects/ListBasedExamples.cs#L121-L129)] +:::code language="csharp" source="./Snippets/classes-and-objects/ListBasedExamples.cs" id="ListAccess"::: The first `Console.WriteLine` outputs `True` because the two lists contain the same number of objects with the same values in the same order. Had `MyList` not defined `operator ==`, the first `Console.WriteLine` would have output `False` because `a` and `b` reference different `MyList` instances. @@ -291,6 +236,67 @@ The garbage collector is allowed wide latitude in deciding when to collect objec The `using` statement provides a better approach to object destruction. -> [!div class="step-by-step"] -> [Previous](statements.md) -> [Next](arrays.md) +## Expressions + +*Expressions* are constructed from *operands* and *operators*. The operators of an expression indicate which operations to apply to the operands. Examples of operators include `+`, `-`, `*`, `/`, and `new`. Examples of operands include literals, fields, local variables, and expressions. + +When an expression contains multiple operators, the *precedence* of the operators controls the order in which the individual operators are evaluated. For example, the expression `x + y * z` is evaluated as `x + (y * z)` because the `*` operator has higher precedence than the `+` operator. + +When an operand occurs between two operators with the same precedence, the *associativity* of the operators controls the order in which the operations are performed: + +* Except for the assignment and null-coalescing operators, all binary operators are *left-associative*, meaning that operations are performed from left to right. For example, `x + y + z` is evaluated as `(x + y) + z`. +* The assignment operators, the null-coalescing `??` and `??=` operators, and the conditional operator `?:` are *right-associative*, meaning that operations are performed from right to left. For example, `x = y = z` is evaluated as `x = (y = z)`. + +Precedence and associativity can be controlled using parentheses. For example, `x + y * z` first multiplies `y` by `z` and then adds the result to `x`, but `(x + y) * z` first adds `x` and `y` and then multiplies the result by `z`. + +Most operators can be [*overloaded*](../language-reference/operators/operator-overloading.md). Operator overloading permits user-defined operator implementations to be specified for operations where one or both of the operands are of a user-defined class or struct type. + +C# provides a number of operators to perform [arithmetic](../language-reference/operators/arithmetic-operators.md), [logical](../language-reference/operators/boolean-logical-operators.md), [bitwise and shift](../language-reference/operators/bitwise-and-shift-operators.md) operations and [equality](../language-reference/operators/equality-operators.md) and [order](../language-reference/operators/comparison-operators.md) comparisons. + +For the complete list of C# operators ordered by precedence level, see [C# operators](../language-reference/operators/index.md). + +## Statements + +The actions of a program are expressed using *statements*. C# supports several different kinds of statements, a number of which are defined in terms of embedded statements. + +- A *block* permits multiple statements to be written in contexts where a single statement is allowed. A block consists of a list of statements written between the delimiters `{` and `}`. +- *Declaration statements* are used to declare local variables and constants. +- *Expression statements* are used to evaluate expressions. Expressions that can be used as statements include method invocations, object allocations using the `new` operator, assignments using `=` and the compound assignment operators, increment and decrement operations using the `++` and `--` operators and `await` expressions. +- *Selection statements* are used to select one of a number of possible statements for execution based on the value of some expression. This group contains the `if` and `switch` statements. +- *Iteration statements* are used to execute repeatedly an embedded statement. This group contains the `while`, `do`, `for`, and `foreach` statements. +- *Jump statements* are used to transfer control. This group contains the `break`, `continue`, `goto`, `throw`, `return`, and `yield` statements. +- The `try`...`catch` statement is used to catch exceptions that occur during execution of a block, and the `try`...`finally` statement is used to specify finalization code that is always executed, whether an exception occurred or not. +- The `checked` and `unchecked` statements are used to control the overflow-checking context for integral-type arithmetic operations and conversions. +- The `lock` statement is used to obtain the mutual-exclusion lock for a given object, execute a statement, and then release the lock. +- The `using` statement is used to obtain a resource, execute a statement, and then dispose of that resource. + +The following lists the kinds of statements that can be used: + +* Local variable declaration. +* Local constant declaration. +* Expression statement. +* `if` statement. +* `switch` statement. +* `while` statement. +* `do` statement. +* `for` statement. +* `foreach` statement. +* `break` statement. +* `continue` statement. +* `goto` statement. +* `return` statement. +* `yield` statement. +* `throw` statements and `try` statements. +* `checked` and `unchecked` statements. +* `lock` statement. +* `using` statement. + +When a method body is a single expression, the method can be defined using a compact expression format, as shown in the following example: + +```csharp +public override ToString() => "This is an object"; +``` + +>[!div class="step-by-step"] +>[Previous](types.md) +>[Next](features.md) diff --git a/docs/csharp/tour-of-csharp/program-structure.md b/docs/csharp/tour-of-csharp/program-structure.md deleted file mode 100644 index afeb04421f7c3..0000000000000 --- a/docs/csharp/tour-of-csharp/program-structure.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: C# Program Structure - A Tour of the C# Language -description: Learn the basic building blocks of a C# program -ms.date: 02/25/2020 -ms.assetid: 984f0314-507f-47a0-af56-9011243f5e65 ---- - -# Program Structure - -The key organizational concepts in C# are ***programs***, ***namespaces***, ***types***, ***members***, and ***assemblies***. C# programs consist of one or more source files. Programs declare types, which contain members and can be organized into namespaces. Classes and interfaces are examples of types. Fields, methods, properties, and events are examples of members. When C# programs are compiled, they're physically packaged into assemblies. Assemblies typically have the file extension `.exe` or `.dll`, depending on whether they implement ***applications*** or ***libraries***, respectively. - -You can create a library project named *acme* using the `dotnet new` command: - -```dotnetcli -dotnet new classlib -o acme -``` - -In that project, declare a class named `Stack` in a namespace called `Acme.Collections`: - -[!code-csharp[Stack](../../../samples/snippets/csharp/tour/program-structure/program.cs#L1-L34)] - -The fully qualified name of this class is `Acme.Collections.Stack`. The class contains several members: a field named `top`, two methods named `Push` and `Pop`, and a nested class named `Entry`. The `Entry` class further contains three members: a field named `next`, a field named `data`, and a constructor. The command: - -```dotnetcli -dotnet build -``` - -compiles the example as a library (code without a `Main` entry point) and produces an assembly named `acme.dll`. - -Assemblies contain executable code in the form of Intermediate Language (IL) instructions, and symbolic information in the form of metadata. Before it's executed, the Just-In-Time (JIT) compiler of .NET Common Language Runtime converts the IL code in an assembly to processor-specific code. - -Because an assembly is a self-describing unit of functionality containing both code and metadata, there's no need for `#include` directives and header files in C#. The public types and members contained in a particular assembly are made available in a C# program simply by referencing that assembly when compiling the program. For example, this program uses the `Acme.Collections.Stack` class from the `acme.dll` assembly: - -[!code-csharp[UsingStack](../../../samples/snippets/csharp/tour/program-structure/Program.cs#L38-L52)] - -The *csproj* file for the preceding program's project must include a reference node for the C# compiler to resolve references to the classes in the `acme.dll` assembly: - -```xml - - - -``` - -After that addition, `dotnet build` creates an executable assembly named `example.exe`, which, when run, produces the output: - -```dotnetcli -100 -10 -1 -``` - -C# permits the source text of a program to be stored in several source files. When a multi-file C# program is compiled, all of the source files are processed together, and the source files can freely reference each other—conceptually, it is as if all the source files were concatenated into one large file before being processed. Forward declarations are never needed in C# because, with few exceptions, declaration order is insignificant. C# does not limit a source file to declaring only one public type nor does it require the name of the source file to match a type declared in the source file. - ->[!div class="step-by-step"] ->[Previous](index.md) ->[Next](types-and-variables.md) diff --git a/docs/csharp/tour-of-csharp/statements.md b/docs/csharp/tour-of-csharp/statements.md deleted file mode 100644 index cbbcd1b954669..0000000000000 --- a/docs/csharp/tour-of-csharp/statements.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: C# Statements - A tour of the C# language -description: You create the actions of a C# program using statements -ms.date: 02/27/2020 -ms.assetid: 5409c379-5622-4fae-88b5-1654276ea8d4 ---- - -# Statements - -The actions of a program are expressed using *statements*. C# supports several different kinds of statements, a number of which are defined in terms of embedded statements. - -A *block* permits multiple statements to be written in contexts where a single statement is allowed. A block consists of a list of statements written between the delimiters `{` and `}`. - -*Declaration statements* are used to declare local variables and constants. - -*Expression statements* are used to evaluate expressions. Expressions that can be used as statements include method invocations, object allocations using the `new` operator, assignments using `=` and the compound assignment operators, increment and decrement operations using the `++` and `--` operators and `await` expressions. - -*Selection statements* are used to select one of a number of possible statements for execution based on the value of some expression. This group contains the `if` and `switch` statements. - -*Iteration statements* are used to execute repeatedly an embedded statement. This group contains the `while`, `do`, `for`, and `foreach` statements. - -*Jump statements* are used to transfer control. This group contains the `break`, `continue`, `goto`, `throw`, `return`, and `yield` statements. - -The `try`...`catch` statement is used to catch exceptions that occur during execution of a block, and the `try`...`finally` statement is used to specify finalization code that is always executed, whether an exception occurred or not. - -The `checked` and `unchecked` statements are used to control the overflow-checking context for integral-type arithmetic operations and conversions. - -The `lock` statement is used to obtain the mutual-exclusion lock for a given object, execute a statement, and then release the lock. - -The `using` statement is used to obtain a resource, execute a statement, and then dispose of that resource. - -The following lists the kinds of statements that can be used, and provides an example for each. - -* Local variable declaration: - - [!code-csharp[Declarations](../../../samples/snippets/csharp/tour/statements/Program.cs#L9-L15)] - -* Local constant declaration: - - [!code-csharp[ConstantDeclarations](../../../samples/snippets/csharp/tour/statements/Program.cs#L17-L22)] - -* Expression statement: - - [!code-csharp[Expressions](../../../samples/snippets/csharp/tour/statements/Program.cs#L24-L31)] - -* `if` statement: - - [!code-csharp[IfStatement](../../../samples/snippets/csharp/tour/statements/Program.cs#L33-L43)] - -* `switch` statement: - - [!code-csharp[SwitchStatement](../../../samples/snippets/csharp/tour/statements/Program.cs#L45-L60)] - -* `while` statement: - - [!code-csharp[WhileStatement](../../../samples/snippets/csharp/tour/statements/Program.cs#L62-L70)] - -* `do` statement: - - [!code-csharp[DoStatement](../../../samples/snippets/csharp/tour/statements/Program.cs#L72-L81)] - -* `for` statement: - - [!code-csharp[ForStatement](../../../samples/snippets/csharp/tour/statements/Program.cs#L83-L89)] - -* `foreach` statement: - - [!code-csharp[ForEachStatement](../../../samples/snippets/csharp/tour/statements/Program.cs#L91-L97)] - -* `break` statement: - - [!code-csharp[BreakStatement](../../../samples/snippets/csharp/tour/statements/Program.cs#L99-L108)] - -* `continue` statement: - - [!code-csharp[ContinueStatement](../../../samples/snippets/csharp/tour/statements/Program.cs#L110-L118)] - -* `goto` statement: - - [!code-csharp[GotoStatement](../../../samples/snippets/csharp/tour/statements/Program.cs#L120-L129)] - -* `return` statement: - - [!code-csharp[ReturnStatement](../../../samples/snippets/csharp/tour/statements/Program.cs#L131-L139)] - -* `yield` statement: - - [!code-csharp[YieldStatement](../../../samples/snippets/csharp/tour/statements/Program.cs#L141-L155)] - -* `throw` statements and `try` statements: - - [!code-csharp[TryThrow](../../../samples/snippets/csharp/tour/statements/Program.cs#L157-L183)] - -* `checked` and `unchecked` statements: - - [!code-csharp[CheckedUncheckedStatement](../../../samples/snippets/csharp/tour/statements/Program.cs#L185-L196)] - -* `lock` statement: - - [!code-csharp[LockStatement](../../../samples/snippets/csharp/tour/statements/Program.cs#L257-L273)] - -* `using` statement: - - [!code-csharp[UsingStatement](../../../samples/snippets/csharp/tour/statements/Program.cs#L198-L206)] - ->[!div class="step-by-step"] ->[Previous](expressions.md) ->[Next](classes-and-objects.md) diff --git a/docs/csharp/tour-of-csharp/types-and-variables.md b/docs/csharp/tour-of-csharp/types-and-variables.md deleted file mode 100644 index 3682fa4c8358b..0000000000000 --- a/docs/csharp/tour-of-csharp/types-and-variables.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: C# Types and Variables - A tour of the C# language -description: Learn about defining types and declaring variables in C# -ms.date: 04/24/2020 -ms.assetid: f8a8051e-0049-43f1-b594-9c84cc7b1224 ---- - -# Types and variables - -There are two kinds of types in C#: *value types* and *reference types*. Variables of value types directly contain their data whereas variables of reference types store references to their data, the latter being known as objects. With reference types, it's possible for two variables to reference the same object and thus possible for operations on one variable to affect the object referenced by the other variable. With value types, the variables each have their own copy of the data, and it isn't possible for operations on one to affect the other (except for `ref` and `out` parameter variables). - -C#'s value types are further divided into *simple types*, *enum types*, *struct types*, and *nullable value types*. C#'s reference types are further divided into *class types*, *interface types*, *array types*, and *delegate types*. - -The following outline provides an overview of C#'s type system. - -- [Value types][ValueTypes] - - [Simple types][SimpleTypes] - - Signed integral: `sbyte`, `short`, `int`, `long` - - Unsigned integral: `byte`, `ushort`, `uint`, `ulong` - - Unicode characters: `char` - - IEEE binary floating-point: `float`, `double` - - High-precision decimal floating-point: `decimal` - - Boolean: `bool` - - [Enum types][EnumTypes] - - User-defined types of the form `enum E {...}` - - [Struct types][StructTypes] - - User-defined types of the form `struct S {...}` - - [Nullable value types][NullableTypes] - - Extensions of all other value types with a `null` value - - [Tuple value types][TupleTypes] - - User-defined types of the form `(T1, T2, ...)` -- [Reference types][ReferenceTypes] - - [Class types][ClassTypes] - - Ultimate base class of all other types: `object` - - Unicode strings: `string` - - User-defined types of the form `class C {...}` - - [Interface types][InterfaceTypes] - - User-defined types of the form `interface I {...}` - - [Array types][ArrayTypes] - - Single- and multi-dimensional, for example, `int[]` and `int[,]` - - [Delegate types][DelegateTypes] - - User-defined types of the form `delegate int D(...)` - -[ValueTypes]: ../language-reference/builtin-types/value-types.md -[SimpleTypes]: ../language-reference/builtin-types/value-types.md#built-in-value-types -[EnumTypes]: ../language-reference/builtin-types/enum.md -[StructTypes]: ../language-reference/builtin-types/struct.md -[NullableTypes]: ../language-reference/builtin-types/nullable-value-types.md -[TupleTypes]: ../language-reference/builtin-types/value-tuples.md -[ReferenceTypes]: ../language-reference/keywords/reference-types.md -[ClassTypes]: ../language-reference/keywords/class.md -[InterfaceTypes]: ../language-reference/keywords/interface.md -[DelegateTypes]: ../language-reference/keywords/delegate.md -[ArrayTypes]: ../programming-guide/arrays/index.md - -For more information about numeric types, see [Integral types](../language-reference/builtin-types/integral-numeric-types.md) and [Floating-point types table](../language-reference/builtin-types/floating-point-numeric-types.md). - -C#'s `bool` type is used to represent Boolean values—values that are either `true` or `false`. - -Character and string processing in C# uses Unicode encoding. The `char` type represents a UTF-16 code unit, and the `string` type represents a sequence of UTF-16 code units. - -C# programs use *type declarations* to create new types. A type declaration specifies the name and the members of the new type. Five of C#'s categories of types are user-definable: class types, struct types, interface types, enum types, and delegate types. - -A `class` type defines a data structure that contains data members (fields) and function members (methods, properties, and others). Class types support single inheritance and polymorphism, mechanisms whereby derived classes can extend and specialize base classes. - -A `struct` type is similar to a class type in that it represents a structure with data members and function members. However, unlike classes, structs are value types and don't typically require heap allocation. Struct types don't support user-specified inheritance, and all struct types implicitly inherit from type `object`. - -An `interface` type defines a contract as a named set of public function members. A `class` or `struct` that implements an `interface` must provide implementations of the interface's function members. An `interface` may inherit from multiple base interfaces, and a `class` or `struct` may implement multiple interfaces. - -A `delegate` type represents references to methods with a particular parameter list and return type. Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters. Delegates are analogous to function types provided by functional languages. They're also similar to the concept of function pointers found in some other languages. Unlike function pointers, delegates are object-oriented and type-safe. - -The `class`, `struct`, `interface`, and `delegate` types all support generics, whereby they can be parameterized with other types. - -An `enum` type is a distinct type with named constants. Every `enum` type has an underlying type, which must be one of the eight integral types. The set of values of an `enum` type is the same as the set of values of the underlying type. - -C# supports single- and multi-dimensional arrays of any type. Unlike the types listed above, array types don't have to be declared before they can be used. Instead, array types are constructed by following a type name with square brackets. For example, `int[]` is a single-dimensional array of `int`, `int[,]` is a two-dimensional array of `int`, and `int[][]` is a single-dimensional array of single-dimensional array of `int`. - -Nullable value types also don't have to be declared before they can be used. For each non-nullable value type `T`, there is a corresponding nullable value type `T?`, which can hold an additional value, `null`. For instance, `int?` is a type that can hold any 32-bit integer or the value `null`. - -C#'s type system is unified such that a value of any type can be treated as an `object`. Every type in C# directly or indirectly derives from the `object` class type, and `object` is the ultimate base class of all types. Values of reference types are treated as objects simply by viewing the values as type `object`. Values of value types are treated as objects by performing *boxing* and *unboxing operations*. In the following example, an `int` value is converted to `object` and back again to `int`. - -[!code-csharp[Boxing](../../../samples/snippets/csharp/tour/types-and-variables/Program.cs#L1-L10)] - -When a value of a value type is assigned to an `object` reference, a "box" is allocated to hold the value. That box is an instance of a reference type, and the value is copied into that box. Conversely, when an `object` reference is cast to a value type, a check is made that the referenced `object` is a box of the correct value type. If the check succeeds, the value in the box is copied to the value type. - -C#'s unified type system effectively means that value types are treated as `object` references "on demand." Because of the unification, general-purpose libraries that use type `object` can be used with all types that derive from `object`, including both reference types and value types. - -There are several kinds of *variables* in C#, including fields, array elements, local variables, and parameters. Variables represent storage locations, and every variable has a type that determines what values can be stored in the variable, as shown below. - -- Non-nullable value type - - A value of that exact type -- Nullable value type - - A `null` value or a value of that exact type -- object - - A `null` reference, a reference to an object of any reference type, or a reference to a boxed value of any value type -- Class type - - A `null` reference, a reference to an instance of that class type, or a reference to an instance of a class derived from that class type -- Interface type - - A `null` reference, a reference to an instance of a class type that implements that interface type, or a reference to a boxed value of a value type that implements that interface type -- Array type - - A `null` reference, a reference to an instance of that array type, or a reference to an instance of a compatible array type -- Delegate type - - A `null` reference or a reference to an instance of a compatible delegate type - -> [!div class="step-by-step"] -> [Previous](program-structure.md) -> [Next](expressions.md) diff --git a/docs/csharp/tour-of-csharp/types.md b/docs/csharp/tour-of-csharp/types.md new file mode 100644 index 0000000000000..ddb8df13c97e9 --- /dev/null +++ b/docs/csharp/tour-of-csharp/types.md @@ -0,0 +1,104 @@ +--- +title: Define types and their members - A tour of C# +description: The building blocks of programs are types. Learn how to create classes, structs, interfaces, and more in C#. +ms.date: 08/03/2020 +--- +# Types and members + +## Classes and objects + +*Classes* are the most fundamental of C#’s types. A class is a data structure that combines state (fields) and actions (methods and other function members) in a single unit. A class provides a definition for dynamically created *instances* of the class, also known as *objects*. Classes support *inheritance* and *polymorphism*, mechanisms whereby *derived classes* can extend and specialize *base classes*. + +New classes are created using class declarations. A class declaration starts with a header that specifies the attributes and modifiers of the class, the name of the class, the base class (if given), and the interfaces implemented by the class. The header is followed by the class body, which consists of a list of member declarations written between the delimiters `{` and `}`. + +The following code shows a declaration of a simple class named `Point`: + +:::code language="csharp" source="./Snippets/classes-and-objects/Point.cs" id="PointClass"::: + +Instances of classes are created using the `new` operator, which allocates memory for a new instance, invokes a constructor to initialize the instance, and returns a reference to the instance. The following statements create two Point objects and store references to those objects in two variables: + +:::code language="csharp" source="./Snippets/classes-and-objects/Program.cs" id="CreatePoints"::: + +The memory occupied by an object is automatically reclaimed when the object is no longer reachable. It's neither necessary nor possible to explicitly deallocate objects in C#. + +### Type parameters + +A class definition may specify a set of type parameters by following the class name with angle brackets enclosing a list of type parameter names. The type parameters can then be used in the body of the class declarations to define the members of the class. In the following example, the type parameters of `Pair` are `TFirst` and `TSecond`: + +:::code language="csharp" source="./Snippets/classes-and-objects/Pair.cs" id="DefinePairClass"::: + +A class type that is declared to take type parameters is called a *generic class type*. Struct, interface, and delegate types can also be generic. +When the generic class is used, type arguments must be provided for each of the type parameters: + +:::code language="csharp" source="./Snippets/classes-and-objects/Program.cs" id="CreatePairObject"::: + +A generic type with type arguments provided, like `Pair` above, is called a *constructed type*. + +### Base classes + +A class declaration may specify a base class by following the class name and type parameters with a colon and the name of the base class. Omitting a base class specification is the same as deriving from type `object`. In the following example, the base class of `Point3D` is `Point`. From the first example, the base class of `Point` is `object`: + +:::code language="csharp" source="./Snippets/classes-and-objects/Point.cs" id="Create3DPoint"::: + +A class inherits the members of its base class. Inheritance means that a class implicitly contains all members of its base class, except for the instance and static constructors, and the finalizers of the base class. A derived class can add new members to those members it inherits, but it can't remove the definition of an inherited member. In the previous example, `Point3D` inherits the `x` and `y` fields from `Point`, and every `Point3D` instance contains three fields, `x`, `y`, and `z`. + +An implicit conversion exists from a class type to any of its base class types. A variable of a class type can reference an instance of that class or an instance of any derived class. For example, given the previous class declarations, a variable of type `Point` can reference either a `Point` or a `Point3D`: + +:::code language="csharp" source="./Snippets/classes-and-objects/Program.cs" id="ImplicitCastToBase"::: + +## Structs + +Classes define types that support inheritance and polymorphism. They enable you to create sophisticated behaviors based on hierarchies of derived classes. By contrast, ***struct*** types are simpler types whose primary purpose is to store data values. Structs cannot declare a base type; they implicitly derive from . You cannot derive other `struct` types from a `struct` type. They are implicitly sealed. + +:::code language="csharp" source="./Snippets/classes-and-objects/Point.cs" id="PointStruct"::: + +## Interfaces + +An ***interface*** defines a contract that can be implemented by classes and structs. An interface can contain methods, properties, events, and indexers. An interface typically doesn't provide implementations of the members it defines—it merely specifies the members that must be supplied by classes or structs that implement the interface. + +Interfaces may employ ***multiple inheritance***. In the following example, the interface `IComboBox` inherits from both `ITextBox` and `IListBox`. + +:::code language="csharp" source="./Snippets/interfaces/Program.cs" id="FirstInterfaces"::: + +Classes and structs can implement multiple interfaces. In the following example, the class `EditBox` implements both `IControl` and `IDataBound`. + +:::code language="csharp" source="./Snippets/interfaces/Program.cs" id="ImplementInterfaces"::: + +When a class or struct implements a particular interface, instances of that class or struct can be implicitly converted to that interface type. For example + +:::code language="csharp" source="./Snippets/interfaces/Program.cs" id="UseInterfaces"::: + +## Enums + +An ***Enum*** type defines a set of constant values. The following `enum` declares constants that define different root vegetables: + +:::code language="csharp" source="./Snippets/types-and-variables/Program.cs" id="EnumDeclaration"::: + +You can also define an `enum` be used in combination as flags. THe following declaration declares a set of flags for the four seasons. Any combination of the seasons may be applied, including an `All` value that includes all seasons: + +:::code language="csharp" source="./Snippets/types-and-variables/Program.cs" id="FlagsEnumDeclaration"::: + +The following example shows declarations of both the preceding enums: + +:::code language="csharp" source="./Snippets/types-and-variables/Program.cs" id="UsingEnums"::: + +## Nullable types + +Variables of any type may be declared as ***non-nullable*** or ***nullable***. A nullable variable can hold an additional `null` value, indicating no value. Nullable Value types (structs or enums) are represented by . Non-nullable and Nullable Reference types are both represented by the underlying reference type. The distinction is represented by metadata read by the compiler and some libraries. The compiler provides warnings when nullable references are de-referenced without first checking their value against `null`. The compiler also provides warnings when non-nullable references are assigned to a value that may be `null`. + +## Tuples + +C# supports ***tuples*** which provides concise syntax to group multiple data elements in a lightweight data structure. You instantiate a tuple by declaring the types and names of the members between `(` and `)`, as shown in the following example: + +```csharp +(double Sum, int Count) t2 = (4.5, 3); +Console.WriteLine($"Sum of {t2.Count} elements is {t2.Sum}."); +// Output: +// Sum of 3 elements is 4.5. +``` + +Tuples provide an alternative when you want a data structure for multiple members, but won't use the building blocks described in the next article. + +>[!div class="step-by-step"] +>[Previous](index.md) +>[Next](program-building-blocks.md) diff --git a/docs/csharp/tutorials/inheritance.md b/docs/csharp/tutorials/inheritance.md index 8fd3efe9580a8..4725a92209ccc 100644 --- a/docs/csharp/tutorials/inheritance.md +++ b/docs/csharp/tutorials/inheritance.md @@ -291,5 +291,4 @@ The following example uses objects derived from `Shape`. It instantiates an arra ## See also -- [Classes and objects](../tour-of-csharp/classes-and-objects.md) - [Inheritance (C# Programming Guide)](../programming-guide/classes-and-structs/inheritance.md) diff --git a/samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Shipped.md b/samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Shipped.md new file mode 100644 index 0000000000000..d567f14248eff --- /dev/null +++ b/samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Shipped.md @@ -0,0 +1,3 @@ +; Shipped analyzer releases +; https://github.com/dotnet/roslyn-analyzers/blob/master/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md + diff --git a/samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Unshipped.md b/samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Unshipped.md new file mode 100644 index 0000000000000..43574499f9ea2 --- /dev/null +++ b/samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Unshipped.md @@ -0,0 +1,3 @@ +; Unshipped analyzer release +; https://github.com/dotnet/roslyn-analyzers/blob/master/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md + diff --git a/samples/snippets/csharp/tour/program-structure/Program.cs b/samples/snippets/csharp/tour/program-structure/Program.cs deleted file mode 100644 index 5a0a175a966e6..0000000000000 --- a/samples/snippets/csharp/tour/program-structure/Program.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -namespace Acme.Collections -{ - public class Stack - { - Entry top; - public void Push(object data) - { - top = new Entry(top, data); - } - - public object Pop() - { - if (top == null) - { - throw new InvalidOperationException(); - } - object result = top.data; - top = top.next; - return result; - } - - class Entry - { - public Entry next; - public object data; - public Entry(Entry next, object data) - { - this.next = next; - this.data = data; - } - } - } -} - -namespace StackExample -{ -using System; -using Acme.Collections; -class Example -{ - static void Main() - { - Stack s = new Stack(); - s.Push(1); - s.Push(10); - s.Push(100); - Console.WriteLine(s.Pop()); - Console.WriteLine(s.Pop()); - Console.WriteLine(s.Pop()); - } -} -} diff --git a/samples/snippets/csharp/tour/program-structure/access-by-line.txt b/samples/snippets/csharp/tour/program-structure/access-by-line.txt deleted file mode 100644 index d4560c2d84721..0000000000000 --- a/samples/snippets/csharp/tour/program-structure/access-by-line.txt +++ /dev/null @@ -1 +0,0 @@ -program.cs: ~/docs/csharp/tour-of-csharp/program-structure.md diff --git a/samples/snippets/csharp/tour/statements/Program.cs b/samples/snippets/csharp/tour/statements/Program.cs deleted file mode 100644 index f3a0e67787852..0000000000000 --- a/samples/snippets/csharp/tour/statements/Program.cs +++ /dev/null @@ -1,274 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; - -namespace Statements -{ - public class Program - { - static void Declarations(string[] args) - { - int a; - int b = 2, c = 3; - a = 1; - Console.WriteLine(a + b + c); - } - - static void ConstantDeclarations(string[] args) - { - const float pi = 3.1415927f; - const int r = 25; - Console.WriteLine(pi * r * r); - } - - static void Expressions(string[] args) - { - int i; - i = 123; // Expression statement - Console.WriteLine(i); // Expression statement - i++; // Expression statement - Console.WriteLine(i); // Expression statement - } - - static void IfStatement(string[] args) - { - if (args.Length == 0) - { - Console.WriteLine("No arguments"); - } - else - { - Console.WriteLine("One or more arguments"); - } - } - - static void SwitchStatement(string[] args) - { - int n = args.Length; - switch (n) - { - case 0: - Console.WriteLine("No arguments"); - break; - case 1: - Console.WriteLine("One argument"); - break; - default: - Console.WriteLine($"{n} arguments"); - break; - } - } - - static void WhileStatement(string[] args) - { - int i = 0; - while (i < args.Length) - { - Console.WriteLine(args[i]); - i++; - } - } - - static void DoStatement(string[] args) - { - string s; - do - { - s = Console.ReadLine(); - Console.WriteLine(s); - } while (!string.IsNullOrEmpty(s)); - } - - - static void ForStatement(string[] args) - { - for (int i = 0; i < args.Length; i++) - { - Console.WriteLine(args[i]); - } - } - - static void ForEachStatement(string[] args) - { - foreach (string s in args) - { - Console.WriteLine(s); - } - } - - static void BreakStatement(string[] args) - { - while (true) - { - string s = Console.ReadLine(); - if (string.IsNullOrEmpty(s)) - break; - Console.WriteLine(s); - } - } - - static void ContinueStatement(string[] args) - { - for (int i = 0; i < args.Length; i++) - { - if (args[i].StartsWith("/")) - continue; - Console.WriteLine(args[i]); - } - } - - static void GoToStatement(string[] args) - { - int i = 0; - goto check; - loop: - Console.WriteLine(args[i++]); - check: - if (i < args.Length) - goto loop; - } - - static int Add(int a, int b) - { - return a + b; - } - static void ReturnStatement(string[] args) - { - Console.WriteLine(Add(1, 2)); - return; - } - - static System.Collections.Generic.IEnumerable Range(int start, int end) - { - for (int i = start; i < end; i++) - { - yield return i; - } - yield break; - } - static void YieldStatement(string[] args) - { - foreach (int i in Range(-10,10)) - { - Console.WriteLine(i); - } - } - - static double Divide(double x, double y) - { - if (y == 0) - throw new DivideByZeroException(); - return x / y; - } - static void TryCatch(string[] args) - { - try - { - if (args.Length != 2) - { - throw new InvalidOperationException("Two numbers required"); - } - double x = double.Parse(args[0]); - double y = double.Parse(args[1]); - Console.WriteLine(Divide(x, y)); - } - catch (InvalidOperationException e) - { - Console.WriteLine(e.Message); - } - finally - { - Console.WriteLine("Good bye!"); - } - } - - static void CheckedUnchecked(string[] args) - { - int x = int.MaxValue; - unchecked - { - Console.WriteLine(x + 1); // Overflow - } - checked - { - Console.WriteLine(x + 1); // Exception - } - } - - static void UsingStatement(string[] args) - { - using (TextWriter w = File.CreateText("test.txt")) - { - w.WriteLine("Line one"); - w.WriteLine("Line two"); - w.WriteLine("Line three"); - } - } - - public static void Main(string[] args) - { - Declarations(args); - - ConstantDeclarations(args); - - Expressions(args); - - IfStatement(args); - - SwitchStatement(args); - - WhileStatement(args); - - Console.WriteLine("Type Mesages. Enter a blank line to end"); - DoStatement(args); - - ForStatement(args); - - ForEachStatement(args); - - Console.WriteLine("Type Mesages. Enter a blank line to end"); - BreakStatement(args); - - ContinueStatement(args); - - GoToStatement(args); - - ReturnStatement(args); - - YieldStatement(args); - - TryCatch(args); - - try { - CheckedUnchecked(args); - } catch (OverflowException) - { - Console.WriteLine("Caught Expected Exception"); - } - - var a = new Account(); - a.Withdraw(-5); - a.Withdraw(2); - - UsingStatement(args); - } - } - - class Account - { - decimal balance; - private readonly object sync = new object(); - public void Withdraw(decimal amount) - { - lock (sync) - { - if (amount > balance) - { - throw new Exception( - "Insufficient funds"); - } - balance -= amount; - } - } - } -} diff --git a/samples/snippets/csharp/tour/statements/access-by-line.txt b/samples/snippets/csharp/tour/statements/access-by-line.txt deleted file mode 100644 index 03bf6dd65cb16..0000000000000 --- a/samples/snippets/csharp/tour/statements/access-by-line.txt +++ /dev/null @@ -1 +0,0 @@ -program.cs: ~/docs/csharp/tour-of-csharp/statements.md diff --git a/samples/snippets/csharp/tour/statements/statements.csproj b/samples/snippets/csharp/tour/statements/statements.csproj deleted file mode 100644 index 9acff6d2afa81..0000000000000 --- a/samples/snippets/csharp/tour/statements/statements.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - Exe - netcoreapp3.1 - - - diff --git a/samples/snippets/csharp/tour/types-and-variables/Program.cs b/samples/snippets/csharp/tour/types-and-variables/Program.cs deleted file mode 100644 index 2907c00b16967..0000000000000 --- a/samples/snippets/csharp/tour/types-and-variables/Program.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -class BoxingExample -{ - static void Main() - { - int i = 123; - object o = i; // Boxing - int j = (int)o; // Unboxing - } -} diff --git a/samples/snippets/csharp/tour/types-and-variables/access-by-line.txt b/samples/snippets/csharp/tour/types-and-variables/access-by-line.txt deleted file mode 100644 index e44a66eb0b656..0000000000000 --- a/samples/snippets/csharp/tour/types-and-variables/access-by-line.txt +++ /dev/null @@ -1,2 +0,0 @@ -Program.cs: ~/docs/csharp/tour-of-csharp/types-and-variables.md - From 0357dbab3defaa32a32f6a3112a6a27bfd879986 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 6 Aug 2020 13:37:22 -0400 Subject: [PATCH 02/11] update and correct all snippets --- .../tour-of-csharp/Snippets/arrays/Program.cs | 75 --- .../Snippets/arrays/access-by-line.txt | 1 - .../Snippets/arrays/arrays.csproj | 8 - .../Snippets/attributes/Program.cs | 66 --- .../Snippets/attributes/access-by-line.txt | 1 - .../Snippets/classes-and-objects/Color.cs | 20 - .../Snippets/classes-and-objects/Entity.cs | 41 -- .../classes-and-objects/Expressions.cs | 94 ---- .../classes-and-objects/ListBasedExamples.cs | 162 ------- .../classes-and-objects/OutExample.cs | 19 - .../classes-and-objects/Overloading.cs | 44 -- .../Snippets/classes-and-objects/Pair.cs | 10 - .../Snippets/classes-and-objects/Point.cs | 37 -- .../Snippets/classes-and-objects/Program.cs | 98 ---- .../classes-and-objects/RefExample.cs | 21 - .../Snippets/classes-and-objects/Squares.cs | 20 - .../classes-and-objects/access-by-line.txt | 12 - .../classes-and-objects.csproj | 8 - .../Snippets/delegates/Program.cs | 53 -- .../Snippets/delegates/access-by-line.txt | 1 - .../Snippets/delegates/delegates.csproj | 8 - .../Snippets/hello/hello.csproj | 8 - .../Snippets/interfaces/Program.cs | 90 ---- .../Snippets/interfaces/access-by-line.txt | 1 - .../Snippets/interfaces/interfaces.csproj | 8 - .../program-structure.csproj | 8 - .../Snippets/types-and-variables/Program.cs | 50 -- .../types-and-variables.csproj | 8 - docs/csharp/tour-of-csharp/features.md | 39 +- docs/csharp/tour-of-csharp/index.md | 10 +- .../tour-of-csharp/program-building-blocks.md | 38 +- .../shared/AcmeStack.cs} | 25 +- .../snippets/shared/ClassesObjects.cs | 455 ++++++++++++++++++ .../snippets/shared/Features.cs | 202 ++++++++ .../shared/HelloWorld.cs} | 0 .../tour-of-csharp/snippets/shared/Program.cs | 14 + .../snippets/shared/StackUsage.cs | 15 + .../shared/TourOfCsharp.csproj} | 3 +- .../tour-of-csharp/snippets/shared/Types.cs | 151 ++++++ docs/csharp/tour-of-csharp/types.md | 37 +- 40 files changed, 895 insertions(+), 1066 deletions(-) delete mode 100644 docs/csharp/tour-of-csharp/Snippets/arrays/Program.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/arrays/access-by-line.txt delete mode 100644 docs/csharp/tour-of-csharp/Snippets/arrays/arrays.csproj delete mode 100644 docs/csharp/tour-of-csharp/Snippets/attributes/Program.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/attributes/access-by-line.txt delete mode 100644 docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Color.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Entity.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Expressions.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/classes-and-objects/ListBasedExamples.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/classes-and-objects/OutExample.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Overloading.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Pair.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Point.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Program.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/classes-and-objects/RefExample.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Squares.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/classes-and-objects/access-by-line.txt delete mode 100644 docs/csharp/tour-of-csharp/Snippets/classes-and-objects/classes-and-objects.csproj delete mode 100644 docs/csharp/tour-of-csharp/Snippets/delegates/Program.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/delegates/access-by-line.txt delete mode 100644 docs/csharp/tour-of-csharp/Snippets/delegates/delegates.csproj delete mode 100644 docs/csharp/tour-of-csharp/Snippets/hello/hello.csproj delete mode 100644 docs/csharp/tour-of-csharp/Snippets/interfaces/Program.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/interfaces/access-by-line.txt delete mode 100644 docs/csharp/tour-of-csharp/Snippets/interfaces/interfaces.csproj delete mode 100644 docs/csharp/tour-of-csharp/Snippets/program-structure/program-structure.csproj delete mode 100644 docs/csharp/tour-of-csharp/Snippets/types-and-variables/Program.cs delete mode 100644 docs/csharp/tour-of-csharp/Snippets/types-and-variables/types-and-variables.csproj rename docs/csharp/tour-of-csharp/{Snippets/program-structure/Program.cs => snippets/shared/AcmeStack.cs} (50%) create mode 100644 docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs create mode 100644 docs/csharp/tour-of-csharp/snippets/shared/Features.cs rename docs/csharp/tour-of-csharp/{Snippets/hello/Program.cs => snippets/shared/HelloWorld.cs} (100%) create mode 100644 docs/csharp/tour-of-csharp/snippets/shared/Program.cs create mode 100644 docs/csharp/tour-of-csharp/snippets/shared/StackUsage.cs rename docs/csharp/tour-of-csharp/{Snippets/attributes/attributes.csproj => snippets/shared/TourOfCsharp.csproj} (60%) create mode 100644 docs/csharp/tour-of-csharp/snippets/shared/Types.cs diff --git a/docs/csharp/tour-of-csharp/Snippets/arrays/Program.cs b/docs/csharp/tour-of-csharp/Snippets/arrays/Program.cs deleted file mode 100644 index c370d857166b4..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/arrays/Program.cs +++ /dev/null @@ -1,75 +0,0 @@ -namespace ArraySample -{ - // - using System; - class ArrayExample - { - static void Main() - { - int[] a = new int[10]; - for (int i = 0; i < a.Length; i++) - { - a[i] = i * i; - } - for (int i = 0; i < a.Length; i++) - { - Console.WriteLine($"a[{i}] = {a[i]}"); - } - } - } - // - - class SampleCode - { - static void ExampleOne() - { - // - int[] a1 = new int[10]; - int[,] a2 = new int[10, 5]; - int[,,] a3 = new int[10, 5, 2]; - // - } - - static void ExampleTwo() - { - // - int[][] a = new int[3][]; - a[0] = new int[10]; - a[1] = new int[5]; - a[2] = new int[20]; - // - } - - static void ExampleThree() - { - // - int[] a = new int[] {1, 2, 3}; - // - } - - static void ExampleFour() - { - // - int[] a = {1, 2, 3}; - // - } - - static void ExampleFive() - { - // - int[] t = new int[3]; - t[0] = 1; - t[1] = 2; - t[2] = 3; - int[] a = t; - // - - // - foreach(int item in a) - { - Console.WriteLine(item); - } - // - } - } -} diff --git a/docs/csharp/tour-of-csharp/Snippets/arrays/access-by-line.txt b/docs/csharp/tour-of-csharp/Snippets/arrays/access-by-line.txt deleted file mode 100644 index 06b7ddbca1f5c..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/arrays/access-by-line.txt +++ /dev/null @@ -1 +0,0 @@ -Program.cs: ~/docs/csharp/tour-of-csharp/arrays.md diff --git a/docs/csharp/tour-of-csharp/Snippets/arrays/arrays.csproj b/docs/csharp/tour-of-csharp/Snippets/arrays/arrays.csproj deleted file mode 100644 index 9acff6d2afa81..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/arrays/arrays.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - Exe - netcoreapp3.1 - - - diff --git a/docs/csharp/tour-of-csharp/Snippets/attributes/Program.cs b/docs/csharp/tour-of-csharp/Snippets/attributes/Program.cs deleted file mode 100644 index 0f2865fee7b66..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/attributes/Program.cs +++ /dev/null @@ -1,66 +0,0 @@ -namespace AttributeSample -{ - // - using System; - - public class HelpAttribute: Attribute - { - string url; - string topic; - public HelpAttribute(string url) - { - this.url = url; - } - - public string Url => url; - - public string Topic { - get { return topic; } - set { topic = value; } - } - } - // - - // - [Help("https://docs.microsoft.com/dotnet/csharp/tour-of-csharp/attributes")] - public class Widget - { - [Help("https://docs.microsoft.com/dotnet/csharp/tour-of-csharp/attributes", - Topic = "Display")] - public void Display(string text) {} - } - // - - - public class Program - { - public static void Main(string[] args) - { - // - Type widgetType = typeof(Widget); - - //Gets every HelpAttribute defined for the Widget type - object[] widgetClassAttributes = widgetType.GetCustomAttributes(typeof(HelpAttribute), false); - - if (widgetClassAttributes.Length > 0) - { - HelpAttribute attr = (HelpAttribute)widgetClassAttributes[0]; - Console.WriteLine($"Widget class help URL : {attr.Url} - Related topic : {attr.Topic}"); - } - - System.Reflection.MethodInfo displayMethod = widgetType.GetMethod(nameof(Widget.Display)); - - //Gets every HelpAttribute defined for the Widget.Display method - object[] displayMethodAttributes = displayMethod.GetCustomAttributes(typeof(HelpAttribute), false); - - if (displayMethodAttributes.Length > 0) - { - HelpAttribute attr = (HelpAttribute)displayMethodAttributes[0]; - Console.WriteLine($"Display method help URL : {attr.Url} - Related topic : {attr.Topic}"); - } - - Console.ReadLine(); - // - } - } -} diff --git a/docs/csharp/tour-of-csharp/Snippets/attributes/access-by-line.txt b/docs/csharp/tour-of-csharp/Snippets/attributes/access-by-line.txt deleted file mode 100644 index 6e06a08dd8ecb..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/attributes/access-by-line.txt +++ /dev/null @@ -1 +0,0 @@ -Program.cs: ~/docs/csharp/tour-of-csharp/attributes.md diff --git a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Color.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Color.cs deleted file mode 100644 index 15fc3431e0762..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Color.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace ClassesAndObjects -{ - // - public class Color - { - public static readonly Color Black = new Color(0, 0, 0); - public static readonly Color White = new Color(255, 255, 255); - public static readonly Color Red = new Color(255, 0, 0); - public static readonly Color Green = new Color(0, 255, 0); - public static readonly Color Blue = new Color(0, 0, 255); - private byte r, g, b; - public Color(byte r, byte g, byte b) - { - this.r = r; - this.g = g; - this.b = b; - } - } - // -} diff --git a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Entity.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Entity.cs deleted file mode 100644 index b84560dc019b7..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Entity.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace ClassesAndObjects -{ - // - using System; - class EntityExample - { - public static void Usage() - { - Entity.SetNextSerialNo(1000); - Entity e1 = new Entity(); - Entity e2 = new Entity(); - Console.WriteLine(e1.GetSerialNo()); // Outputs "1000" - Console.WriteLine(e2.GetSerialNo()); // Outputs "1001" - Console.WriteLine(Entity.GetNextSerialNo()); // Outputs "1002" - } - } - // - // - class Entity - { - static int nextSerialNo; - int serialNo; - public Entity() - { - serialNo = nextSerialNo++; - } - public int GetSerialNo() - { - return serialNo; - } - public static int GetNextSerialNo() - { - return nextSerialNo; - } - public static void SetNextSerialNo(int value) - { - nextSerialNo = value; - } - } - // -} \ No newline at end of file diff --git a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Expressions.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Expressions.cs deleted file mode 100644 index e0d5c5db0d772..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Expressions.cs +++ /dev/null @@ -1,94 +0,0 @@ -namespace ClassesAndObjects -{ - // - using System; - using System.Collections.Generic; - public abstract class Expression - { - public abstract double Evaluate(Dictionary vars); - } - public class Constant: Expression - { - double value; - public Constant(double value) - { - this.value = value; - } - public override double Evaluate(Dictionary vars) - { - return value; - } - } - public class VariableReference: Expression - { - string name; - public VariableReference(string name) - { - this.name = name; - } - public override double Evaluate(Dictionary vars) - { - object value = vars[name]; - if (value == null) - { - throw new Exception("Unknown variable: " + name); - } - return Convert.ToDouble(value); - } - } - public class Operation: Expression - { - Expression left; - char op; - Expression right; - public Operation(Expression left, char op, Expression right) - { - this.left = left; - this.op = op; - this.right = right; - } - public override double Evaluate(Dictionary vars) - { - double x = left.Evaluate(vars); - double y = right.Evaluate(vars); - switch (op) { - case '+': return x + y; - case '-': return x - y; - case '*': return x * y; - case '/': return x / y; - } - throw new Exception("Unknown operator"); - } - } - // -} - -namespace ClassesAndObjects -{ - // - using System; - using System.Collections.Generic; - class InheritanceExample - { - public static void ExampleUsage() - { - Expression e = new Operation( - new VariableReference("x"), - '*', - new Operation( - new VariableReference("y"), - '+', - new Constant(2) - ) - ); - Dictionary vars = new Dictionary(); - vars["x"] = 3; - vars["y"] = 5; - Console.WriteLine(e.Evaluate(vars)); // Outputs "21" - vars["x"] = 1.5; - vars["y"] = 9; - Console.WriteLine(e.Evaluate(vars)); // Outputs "16.5" - } - } - // -} \ No newline at end of file diff --git a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/ListBasedExamples.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/ListBasedExamples.cs deleted file mode 100644 index 743053afaabce..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/ListBasedExamples.cs +++ /dev/null @@ -1,162 +0,0 @@ -namespace ListExamples -{ - using System; - // - public class MyList - { - // Constant - const int defaultCapacity = 4; - - // Fields - T[] items; - int count; - - // Constructor - public MyList(int capacity = defaultCapacity) - { - items = new T[capacity]; - } - - // Properties - public int Count => count; - - public int Capacity - { - get { return items.Length; } - set - { - if (value < count) value = count; - if (value != items.Length) - { - T[] newItems = new T[value]; - Array.Copy(items, 0, newItems, 0, count); - items = newItems; - } - } - } - - // Indexer - public T this[int index] - { - get - { - return items[index]; - } - set - { - items[index] = value; - OnChanged(); - } - } - - // Methods - public void Add(T item) - { - if (count == Capacity) Capacity = count * 2; - items[count] = item; - count++; - OnChanged(); - } - protected virtual void OnChanged() => - Changed?.Invoke(this, EventArgs.Empty); - - public override bool Equals(object other) => - Equals(this, other as MyList); - - static bool Equals(MyList a, MyList b) - { - if (Object.ReferenceEquals(a, null)) return Object.ReferenceEquals(b, null); - if (Object.ReferenceEquals(b, null) || a.count != b.count) - return false; - for (int i = 0; i < a.count; i++) - { - if (!object.Equals(a.items[i], b.items[i])) - { - return false; - } - } - return true; - } - - // Event - public event EventHandler Changed; - - // Operators - public static bool operator ==(MyList a, MyList b) => - Equals(a, b); - - public static bool operator !=(MyList a, MyList b) => - !Equals(a, b); - } - // - - public class ExampleCode - { - public static void ListExampleOne() - { - // - MyList list1 = new MyList(); - MyList list2 = new MyList(10); - // - } - - public static void ListExampleTwo() - { - // - MyList names = new MyList(); - names.Capacity = 100; // Invokes set accessor - int i = names.Count; // Invokes get accessor - int j = names.Capacity; // Invokes get accessor - // - } - - public static void ListExampleThree() - { - // - MyList names = new MyList(); - names.Add("Liz"); - names.Add("Martha"); - names.Add("Beth"); - for (int i = 0; i < names.Count; i++) - { - string s = names[i]; - names[i] = s.ToUpper(); - } - // - } - public static void ListExampleFour() - { - // - MyList a = new MyList(); - a.Add(1); - a.Add(2); - MyList b = new MyList(); - b.Add(1); - b.Add(2); - Console.WriteLine(a == b); // Outputs "True" - b.Add(3); - Console.WriteLine(a == b); // Outputs "False" - // - } - } - - // - class EventExample - { - static int changeCount; - static void ListChanged(object sender, EventArgs e) - { - changeCount++; - } - public static void Usage() - { - MyList names = new MyList(); - names.Changed += new EventHandler(ListChanged); - names.Add("Liz"); - names.Add("Martha"); - names.Add("Beth"); - Console.WriteLine(changeCount); // Outputs "3" - } - } - // -} \ No newline at end of file diff --git a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/OutExample.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/OutExample.cs deleted file mode 100644 index 838b4b9ebee1a..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/OutExample.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace ClassesAndObjects -{ - using System; - // - class OutExample - { - static void Divide(int x, int y, out int result, out int remainder) - { - result = x / y; - remainder = x % y; - } - public static void OutUsage() - { - Divide(10, 3, out int res, out int rem); - Console.WriteLine("{0} {1}", res, rem); // Outputs "3 1" - } - } - // -} diff --git a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Overloading.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Overloading.cs deleted file mode 100644 index 61821daf8f82d..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Overloading.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace ClassesAndObjects -{ - // - using System; - class OverloadingExample - { - static void F() - { - Console.WriteLine("F()"); - } - static void F(object x) - { - Console.WriteLine("F(object)"); - } - static void F(int x) - { - Console.WriteLine("F(int)"); - } - static void F(double x) - { - Console.WriteLine("F(double)"); - } - static void F(T x) - { - Console.WriteLine("F(T)"); - } - static void F(double x, double y) - { - Console.WriteLine("F(double, double)"); - } - public static void UsageExample() - { - F(); // Invokes F() - F(1); // Invokes F(int) - F(1.0); // Invokes F(double) - F("abc"); // Invokes F(string) - F((double)1); // Invokes F(double) - F((object)1); // Invokes F(object) - F(1); // Invokes F(int) - F(1, 1); // Invokes F(double, double) - } - } - // -} \ No newline at end of file diff --git a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Pair.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Pair.cs deleted file mode 100644 index 3ead20ba71ce0..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Pair.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ClassesAndObjects -{ - // - public class Pair - { - public TFirst First; - public TSecond Second; - } - // -} \ No newline at end of file diff --git a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Point.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Point.cs deleted file mode 100644 index 6457c3af638a3..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Point.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace ClassesAndObjects -{ - // - public class Point - { - public int x, y; - public Point(int x, int y) - { - this.x = x; - this.y = y; - } - } - // - // - public class Point3D: Point - { - public int z; - public Point3D(int x, int y, int z) : - base(x, y) - { - this.z = z; - } - } - // -} - -namespace DeclareTypes -{ - // - public struct Point - { - public double X { get; } - public double Y { get; } - public Point(double x, double y) => (X, Y) = (x, y); - } - // -} \ No newline at end of file diff --git a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Program.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Program.cs deleted file mode 100644 index e067b50ef9604..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Program.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; - -namespace ClassesAndObjects -{ - public class Program - { - static void PointExample() - { - // - Point p1 = new Point(0, 0); - Point p2 = new Point(10, 20); - // - } - - static void PairExample() - { - // - Pair pair = new Pair { First = 1, Second = "two" }; - int i = pair.First; // TFirst is int - string s = pair.Second; // TSecond is string - // - } - - static void Point3DExample() - { - // - Point a = new Point(10, 20); - Point b = new Point3D(10, 20, 30); - // - } - - static void StringFormatExample() - { - // - int x = 3, y = 4, z = 5; - - string s = "x={0} y={1} z={2}"; - object[] args = new object[3]; - args[0] = x; - args[1] = y; - args[2] = z; - Console.WriteLine(s, args); - // - } - - static void ExpressionExample() - { - // - Expression e = new Operation( - new VariableReference("x"), - '+', - new Constant(3)); - // - } - - public static void Main(string[] args) - { - PointExample(); - PairExample(); - Point3DExample(); - RefExample.SwapExample(); - OutExample.OutUsage(); - - // - int x = 3, y = 4, z = 5; - Console.WriteLine("x={0} y={1} z={2}", x, y, z); - // - - Squares.WriteSquares(); - - EntityExample.Usage(); - - ExpressionExample(); - - InheritanceExample.ExampleUsage(); - - OverloadingExample.UsageExample(); - - ListExamples.ExampleCode.ListExampleOne(); - ListExamples.ExampleCode.ListExampleTwo(); - ListExamples.ExampleCode.ListExampleThree(); - ListExamples.EventExample.Usage(); - ListExamples.ExampleCode.ListExampleFour(); - } - } -} - -namespace Snippets -{ - // - public class Console - { - public static void Write(string fmt, params object[] args) { } - public static void WriteLine(string fmt, params object[] args) { } - // ... - } - // -} diff --git a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/RefExample.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/RefExample.cs deleted file mode 100644 index b9f821df406a4..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/RefExample.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace ClassesAndObjects -{ - using System; - // - class RefExample - { - static void Swap(ref int x, ref int y) - { - int temp = x; - x = y; - y = temp; - } - public static void SwapExample() - { - int i = 1, j = 2; - Swap(ref i, ref j); - Console.WriteLine($"{i} {j}"); // Outputs "2 1" - } - } - // -} \ No newline at end of file diff --git a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Squares.cs b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Squares.cs deleted file mode 100644 index f2ceb47b87c80..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/Squares.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace ClassesAndObjects -{ - using System; - // - class Squares - { - public static void WriteSquares() - { - int i = 0; - int j; - while (i < 10) - { - j = i * i; - Console.WriteLine($"{i} x {i} = {j}"); - i = i + 1; - } - } - } - // -} \ No newline at end of file diff --git a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/access-by-line.txt b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/access-by-line.txt deleted file mode 100644 index 0e8c4457f4924..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/access-by-line.txt +++ /dev/null @@ -1,12 +0,0 @@ -Program.cs: ~/docs/csharp/tour-of-csharp/classes-and-objects.md -Pair.cs: ~/docs/csharp/tour-of-csharp/classes-and-objects.md -Point.cs: ~/docs/csharp/tour-of-csharp/classes-and-objects.md -Color.cs: ~/docs/csharp/tour-of-csharp/classes-and-objects.md -RefExample.cs: ~/docs/csharp/tour-of-csharp/classes-and-objects.md -OutExample.cs: ~/docs/csharp/tour-of-csharp/classes-and-objects.md -Squares.cs: ~/docs/csharp/tour-of-csharp/classes-and-objects.md -Entity.cs: ~/docs/csharp/tour-of-csharp/classes-and-objects.md -Expressions.cs: ~/docs/csharp/tour-of-csharp/classes-and-objects.md -Overloading.cs: ~/docs/csharp/tour-of-csharp/classes-and-objects.md -ListBasedExamples.cs: ~/docs/csharp/tour-of-csharp/classes-and-objects.md - diff --git a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/classes-and-objects.csproj b/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/classes-and-objects.csproj deleted file mode 100644 index 9acff6d2afa81..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/classes-and-objects/classes-and-objects.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - Exe - netcoreapp3.1 - - - diff --git a/docs/csharp/tour-of-csharp/Snippets/delegates/Program.cs b/docs/csharp/tour-of-csharp/Snippets/delegates/Program.cs deleted file mode 100644 index 2b492a3de10d4..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/delegates/Program.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace DelegateTour -{ - // - using System; - delegate double Function(double x); - class Multiplier - { - double factor; - public Multiplier(double factor) - { - this.factor = factor; - } - public double Multiply(double x) - { - return x * factor; - } - } - class DelegateExample - { - static double[] Apply(double[] a, Function f) - { - double[] result = new double[a.Length]; - for (int i = 0; i < a.Length; i++) result[i] = f(a[i]); - return result; - } - static void Main() - { - double[] a = {0.0, 0.5, 1.0}; - double[] squares = Apply(a, (x) => x * x); - double[] sines = Apply(a, Math.Sin); - Multiplier m = new Multiplier(2.0); - double[] doubles = Apply(a, m.Multiply); - } - } - // - - class Lambda - { - static void ApplyDelegate() - { - double[] a = {0.0, 0.5, 1.0}; - // - double[] doubles = Apply(a, (double x) => x * 2.0); - // - } - static double[] Apply(double[] a, Function f) - { - double[] result = new double[a.Length]; - for (int i = 0; i < a.Length; i++) result[i] = f(a[i]); - return result; - } - } -} diff --git a/docs/csharp/tour-of-csharp/Snippets/delegates/access-by-line.txt b/docs/csharp/tour-of-csharp/Snippets/delegates/access-by-line.txt deleted file mode 100644 index af6897c364fe0..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/delegates/access-by-line.txt +++ /dev/null @@ -1 +0,0 @@ -Program.cs: ~/docs/csharp/tour-of-csharp/delegates.md diff --git a/docs/csharp/tour-of-csharp/Snippets/delegates/delegates.csproj b/docs/csharp/tour-of-csharp/Snippets/delegates/delegates.csproj deleted file mode 100644 index 9acff6d2afa81..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/delegates/delegates.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - Exe - netcoreapp3.1 - - - diff --git a/docs/csharp/tour-of-csharp/Snippets/hello/hello.csproj b/docs/csharp/tour-of-csharp/Snippets/hello/hello.csproj deleted file mode 100644 index 9acff6d2afa81..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/hello/hello.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - Exe - netcoreapp3.1 - - - diff --git a/docs/csharp/tour-of-csharp/Snippets/interfaces/Program.cs b/docs/csharp/tour-of-csharp/Snippets/interfaces/Program.cs deleted file mode 100644 index fb5251a003830..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/interfaces/Program.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; - -namespace Interfaces -{ - // - interface IControl - { - void Paint(); - } - interface ITextBox: IControl - { - void SetText(string text); - } - interface IListBox: IControl - { - void SetItems(string[] items); - } - interface IComboBox: ITextBox, IListBox {} - // - - // - interface IDataBound - { - void Bind(Binder b); - } - public class EditBox: IControl, IDataBound - { - public void Paint() { } - public void Bind(Binder b) { } - } - // - - public class Program - { - static void UsageOne() - { - // - EditBox editBox = new EditBox(); - IControl control = editBox; - IDataBound dataBound = editBox; - // - } - - static void UsageTwo() - { - // - object obj = new EditBox(); - IControl control = (IControl)obj; - IDataBound dataBound = (IDataBound)obj; - // - } - - public static void Main(string[] args) - { - - } - - - } - - public class Binder {} -} - -namespace ExplicitInterface -{ - using Interfaces; - - // - public class EditBox: IControl, IDataBound - { - void IControl.Paint() { } - void IDataBound.Bind(Binder b) { } - } - // - - class UsageCode - { - static void Example() - { - /* - EditBox editBox = new EditBox(); - editBox.Paint(); // Error, no such method - IControl control = editBox; - control.Paint(); // Ok - - */ - } - } - -} diff --git a/docs/csharp/tour-of-csharp/Snippets/interfaces/access-by-line.txt b/docs/csharp/tour-of-csharp/Snippets/interfaces/access-by-line.txt deleted file mode 100644 index 510ab4b324d96..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/interfaces/access-by-line.txt +++ /dev/null @@ -1 +0,0 @@ -Program.cs: ~/docs/csharp/tour-of-csharp/interfaces.md diff --git a/docs/csharp/tour-of-csharp/Snippets/interfaces/interfaces.csproj b/docs/csharp/tour-of-csharp/Snippets/interfaces/interfaces.csproj deleted file mode 100644 index 9acff6d2afa81..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/interfaces/interfaces.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - Exe - netcoreapp3.1 - - - diff --git a/docs/csharp/tour-of-csharp/Snippets/program-structure/program-structure.csproj b/docs/csharp/tour-of-csharp/Snippets/program-structure/program-structure.csproj deleted file mode 100644 index 9acff6d2afa81..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/program-structure/program-structure.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - Exe - netcoreapp3.1 - - - diff --git a/docs/csharp/tour-of-csharp/Snippets/types-and-variables/Program.cs b/docs/csharp/tour-of-csharp/Snippets/types-and-variables/Program.cs deleted file mode 100644 index 4d85d1d45a4f3..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/types-and-variables/Program.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -class BoxingExample -{ - // - // A traditional enumeration of some root vegetables. - public enum SomeRootVegetables - { - HorseRadish, - Radish, - Turnip - } - // - - // - // A bit field or flag enumeration of harvesting seasons. - [Flags] - public enum Seasons - { - None = 0, - Summer = 1, - Autumn = 2, - Winter = 4, - Spring = 8, - All = Summer | Autumn | Winter | Spring - } - // - - static void Main() - { - // - int i = 123; - Console.WriteLine($"Value of i: {i}"); - object o = i; // Boxing - Console.WriteLine($"Initial value of o: {o}"); - o = 456; - Console.WriteLine($"Modified value of o: {o}"); - int j = (int)o; // Unboxing - Console.WriteLine($"Value of unboxed j: {j}"); - Console.WriteLine($"Final value of i: {i}"); - // - - // - var turnip = SomeRootVegetables.Turnip; - - var spring = Seasons.Spring; - var startingOnEquinox = Seasons.Spring | Seasons.Autumn; - var theYear = Seasons.All; - // - } -} diff --git a/docs/csharp/tour-of-csharp/Snippets/types-and-variables/types-and-variables.csproj b/docs/csharp/tour-of-csharp/Snippets/types-and-variables/types-and-variables.csproj deleted file mode 100644 index 9acff6d2afa81..0000000000000 --- a/docs/csharp/tour-of-csharp/Snippets/types-and-variables/types-and-variables.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - Exe - netcoreapp3.1 - - - diff --git a/docs/csharp/tour-of-csharp/features.md b/docs/csharp/tour-of-csharp/features.md index 1dbbd95224a13..6b7f3183ec1e8 100644 --- a/docs/csharp/tour-of-csharp/features.md +++ b/docs/csharp/tour-of-csharp/features.md @@ -17,34 +17,34 @@ Array types are reference types, and the declaration of an array variable simply The following example creates an array of `int` elements, initializes the array, and prints out the contents of the array. -:::code language="csharp" source="./Snippets/arrays/Program.cs" id="ArraysSample"::: +:::code language="csharp" source="./snippets/shared/Features.cs" id="ArraysSample"::: This example creates and operates on a ***single-dimensional array***. C# also supports ***multi-dimensional arrays***. The number of dimensions of an array type, also known as the ***rank*** of the array type, is one plus the number of commas written between the square brackets of the array type. The following example allocates a single-dimensional, a two-dimensional, and a three-dimensional array, respectively. -:::code language="csharp" source="./Snippets/arrays/Program.cs" id="DeclareArrays"::: +:::code language="csharp" source="./snippets/shared/Features.cs" id="DeclareArrays"::: The `a1` array contains 10 elements, the `a2` array contains 50 (10 × 5) elements, and the `a3` array contains 100 (10 × 5 × 2) elements. The element type of an array can be any type, including an array type. An array with elements of an array type is sometimes called a ***jagged array*** because the lengths of the element arrays don't all have to be the same. The following example allocates an array of arrays of `int`: -:::code language="csharp" source="./Snippets/arrays/Program.cs" id="ArrayOfArrays"::: +:::code language="csharp" source="./snippets/shared/Features.cs" id="ArrayOfArrays"::: The first line creates an array with three elements, each of type `int[]` and each with an initial value of `null`. The subsequent lines then initialize the three elements with references to individual array instances of varying lengths. The new operator permits the initial values of the array elements to be specified using an ***array initializer***, which is a list of expressions written between the delimiters `{` and `}`. The following example allocates and initializes an `int[]` with three elements. -:::code language="csharp" source="./Snippets/arrays/Program.cs" id="SnippetInitialize"::: +:::code language="csharp" source="./snippets/shared/Features.cs" id="InitializeArray"::: The length of the array is inferred from the number of expressions between { and }. Local variable and field declarations can be shortened further such that the array type does not have to be restated. -:::code language="csharp" source="./Snippets/arrays/Program.cs" id="InitializeShortened"::: +:::code language="csharp" source="./snippets/shared/Features.cs" id="InitializeShortened"::: Both of the previous examples are equivalent to the following code: -:::code language="csharp" source="./Snippets/arrays/Program.cs" id="InitializeGenerated"::: +:::code language="csharp" source="./snippets/shared/Features.cs" id="InitializeGenerated"::: The `foreach` statement can be used to enumerate the elements of any collection. The following code enumerates the array from the preceding example: -:::code language="csharp" source="./Snippets/arrays/Program.cs" id="EnumerateArray"::: +:::code language="csharp" source="./snippets/shared/Features.cs" id="EnumerateArray"::: The `foreach` statement uses the interface, so can work with any collection. @@ -52,9 +52,7 @@ The `foreach` statement uses the , but can be any type that supports the awaiter pattern. This enables you to write code that reads as its synchronous counterpart, but executes asynchronously. For example, the following code downloads the home page for [Microsoft docs](https://docs.microsoft.com): -```csharp -public async Task RetrieveDocsHomePage() -{ - var client = new HttpClient(); - byte[] content = await client.GetByteArrayAsync("https://docs.microsoft.com/en-us/"); - - Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: Finished downloading."); - return content.Length; -} -``` +:::code language="csharp" source="./snippets/shared/Features.cs" id="AsyncExample"::: This small sample shows the major features for asynchronous programming: @@ -107,11 +96,11 @@ Types, members, and other entities in a C# program support modifiers that contro The following example declares a `HelpAttribute` attribute that can be placed on program entities to provide links to their associated documentation. -:::code language="csharp" source="./Snippets/attributes/Program.cs" id="DefineAttribute"::: +:::code language="csharp" source="./snippets/shared/Features.cs" id="DefineAttribute"::: All attribute classes derive from the base class provided by the standard library. Attributes can be applied by giving their name, along with any arguments, inside square brackets just before the associated declaration. If an attribute’s name ends in `Attribute`, that part of the name can be omitted when the attribute is referenced. For example, the `HelpAttribute` can be used as follows. -:::code language="csharp" source="./Snippets/attributes/Program.cs" id="UseAttributes"::: +:::code language="csharp" source="./snippets/shared/Features.cs" id="UseAttributes"::: This example attaches a `HelpAttribute` to the `Widget` class. It adds another `HelpAttribute` to the `Display` method in the class. The public constructors of an attribute class control the information that must be provided when the attribute is attached to a program entity. Additional information can be provided by referencing public read-write properties of the attribute class (such as the reference to the `Topic` property previously). @@ -119,7 +108,7 @@ The metadata defined by attributes can be read and manipulated at runtime using The following code sample demonstrates how to get the `HelpAttribute` instances associated to the `Widget` class and its `Display` method. -:::code language="csharp" source="./Snippets/attributes/Program.cs" id="SnippetReadAttributes"::: +:::code language="csharp" source="./snippets/shared/attributes/Program.cs" id="ReadAttributes"::: ## Learn more diff --git a/docs/csharp/tour-of-csharp/index.md b/docs/csharp/tour-of-csharp/index.md index 528ffe0388430..77c3d4c47938d 100644 --- a/docs/csharp/tour-of-csharp/index.md +++ b/docs/csharp/tour-of-csharp/index.md @@ -18,7 +18,7 @@ To ensure that C# programs and libraries can evolve over time in a compatible ma The "Hello, World" program is traditionally used to introduce a programming language. Here it is in C#: -:::code language="csharp" interactive="try-dotnet" source="./Snippets/hello/Program.cs"::: +:::code language="csharp" interactive="try-dotnet" source="./snippets/shared/HelloWorld.cs"::: The "Hello, World" program starts with a `using` directive that references the `System` namespace. Namespaces provide a hierarchical means of organizing C# programs and libraries. Namespaces contain types and other namespaces—for example, the `System` namespace contains a number of types, such as the `Console` class referenced in the program, and a number of other namespaces, such as `IO` and `Collections`. A `using` directive that references a given namespace enables unqualified use of the types that are members of that namespace. Because of the `using` directive, the program can use `Console.WriteLine` as shorthand for `System.Console.WriteLine`. @@ -77,7 +77,7 @@ Nullable value types also don't have to be declared before they can be used. For C#'s type system is unified such that a value of any type can be treated as an `object`. Every type in C# directly or indirectly derives from the `object` class type, and `object` is the ultimate base class of all types. Values of reference types are treated as objects simply by viewing the values as type `object`. Values of value types are treated as objects by performing *boxing* and *unboxing operations*. In the following example, an `int` value is converted to `object` and back again to `int`. -:::code language="csharp" interactive="try-dotnet-method" source="./Snippets/types-and-variables/Program.cs" id="boxing" ::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/shared/types-and-variables/Program.cs" id="boxing" ::: When a value of a value type is assigned to an `object` reference, a "box" is allocated to hold the value. That box is an instance of a reference type, and the value is copied into that box. Conversely, when an `object` reference is cast to a value type, a check is made that the referenced `object` is a box of the correct value type. If the check succeeds, the value in the box is copied to the value type. @@ -106,7 +106,7 @@ The key organizational concepts in C# are ***programs***, ***namespaces***, ***t As a small example, consider an assembly that contains the following code: -:::code language="csharp" source="./Snippets/program-structure/Program.cs" id="SnippetStackExample"::: +:::code language="csharp" source="./snippets/shared/AcmeStack.cs"::: The fully qualified name of this class is `Acme.Collections.Stack`. The class contains several members: a field named `top`, two methods named `Push` and `Pop`, and a nested class named `Entry`. The `Entry` class further contains three members: a field named `next`, a field named `data`, and a constructor. The `Stack` is a *generic* class. It has one type parameter, `T` that is replaced with a concrete type when it's used. @@ -117,9 +117,9 @@ Assemblies contain executable code in the form of Intermediate Language (IL) ins Because an assembly is a self-describing unit of functionality containing both code and metadata, there's no need for `#include` directives and header files in C#. The public types and members contained in a particular assembly are made available in a C# program simply by referencing that assembly when compiling the program. For example, this program uses the `Acme.Collections.Stack` class from the `acme.dll` assembly: -:::code language="csharp" source="./Snippets/program-structure/Program.cs" id="SnippetStackUsage"::: +:::code language="csharp" source="./snippets/shared/StackUsage.cs"::: -To compile this program, you would need to *reference* the assesmbly containing the stack class defined in the earlier example. +To compile this program, you would need to *reference* the assembly containing the stack class defined in the earlier example. C# programs can be stored in several source files. When a C# program is compiled, all of the source files are processed together, and the source files can freely reference each other. Conceptually, it's as if all the source files were concatenated into one large file before being processed. Forward declarations are never needed in C# because, with few exceptions, declaration order is insignificant. C# doesn't limit a source file to declaring only one public type nor does it require the name of the source file to match a type declared in the source file. diff --git a/docs/csharp/tour-of-csharp/program-building-blocks.md b/docs/csharp/tour-of-csharp/program-building-blocks.md index a6acf8d2bb7c0..75691075c7efe 100644 --- a/docs/csharp/tour-of-csharp/program-building-blocks.md +++ b/docs/csharp/tour-of-csharp/program-building-blocks.md @@ -45,7 +45,7 @@ A field declared without the static modifier defines an instance field. Every in In the following example, each instance of the `Color` class has a separate copy of the `r`, `g`, and `b` instance fields, but there's only one copy of the `Black`, `White`, `Red`, `Green`, and `Blue` static fields: -:::code language="csharp" source="./Snippets/classes-and-objects/Color.cs" id="ColorClassDefinition"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="ColorClassDefinition"::: As shown in the previous example, *read-only fields* may be declared with a `readonly` modifier. Assignment to a `readonly` field can only occur as part of the field’s declaration or in a constructor in the same class. @@ -69,23 +69,23 @@ Value parameters can be optional, by specifying a default value so that correspo A *reference parameter* is used for passing arguments by reference. The argument passed for a reference parameter must be a variable with a definite value, and during execution of the method, the reference parameter represents the same storage location as the argument variable. A reference parameter is declared with the `ref` modifier. The following example shows the use of `ref` parameters. -:::code language="csharp" source="./Snippets/classes-and-objects/RefExample.cs" id="RefExample"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="RefExample"::: An *output parameter* is used for passing arguments by reference. It's similar to a reference parameter, except that it doesn't require that you explicitly assign a value to the caller-provided argument. An output parameter is declared with the `out` modifier. The following example shows the use of `out` parameters using the syntax introduced in C# 7. -:::code language="csharp" source="./Snippets/classes-and-objects/OutExample.cs" id="OutExample"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="OutExample"::: A *parameter array* permits a variable number of arguments to be passed to a method. A parameter array is declared with the `params` modifier. Only the last parameter of a method can be a parameter array, and the type of a parameter array must be a single-dimensional array type. The Write and WriteLine methods of the class are good examples of parameter array usage. They're declared as follows. -:::code language="csharp" source="./Snippets/classes-and-objects/Program.cs" id="ConsoleExtract"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="ConsoleExtract"::: Within a method that uses a parameter array, the parameter array behaves exactly like a regular parameter of an array type. However, in an invocation of a method with a parameter array, it's possible to pass either a single argument of the parameter array type or any number of arguments of the element type of the parameter array. In the latter case, an array instance is automatically created and initialized with the given arguments. This example -:::code language="csharp" source="./Snippets/classes-and-objects/Program.cs" id="UseParamsArgs"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="UseParamsArgs"::: is equivalent to writing the following. -:::code language="csharp" source="./Snippets/classes-and-objects/Program.cs" id="CompilerParams"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="CompilerParams"::: ### Method body and local variables @@ -93,7 +93,7 @@ A method’s body specifies the statements to execute when the method is invoked A method body can declare variables that are specific to the invocation of the method. Such variables are called *local variables*. A local variable declaration specifies a type name, a variable name, and possibly an initial value. The following example declares a local variable `i` with an initial value of zero and a local variable `j` with no initial value. -:::code language="csharp" source="./Snippets/classes-and-objects/Squares.cs" id="SquaresClass"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="SquaresClass"::: C# requires a local variable to be *definitely assigned* before its value can be obtained. For example, if the declaration of the previous `i` didn't include an initial value, the compiler would report an error for the subsequent usages of `i` because `i` wouldn't be definitely assigned at those points in the program. @@ -107,7 +107,7 @@ A method declared without a static modifier is an *instance method*. An instance The following `Entity` class has both static and instance members. -:::code language="csharp" source="./Snippets/classes-and-objects/Entity.cs" id="EntityClass"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="EntityClass"::: Each `Entity` instance contains a serial number (and presumably some other information that isn't shown here). The `Entity` constructor (which is like an instance method) initializes the new instance with the next available serial number. Because the constructor is an instance member, it's permitted to access both the `serialNo` instance field and the `nextSerialNo` static field. @@ -115,7 +115,7 @@ The `GetNextSerialNo` and `SetNextSerialNo` static methods can access the `nextS The following example shows the use of the Entity class. -:::code language="csharp" source="./Snippets/classes-and-objects/Entity.cs" id="UsingEntity"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="UsingEntity"::: The `SetNextSerialNo` and `GetNextSerialNo` static methods are invoked on the class whereas the `GetSerialNo` instance method is invoked on instances of the class. @@ -131,11 +131,11 @@ An *abstract method* is a virtual method with no implementation. An abstract met The following example declares an abstract class, `Expression`, which represents an expression tree node, and three derived classes, `Constant`, `VariableReference`, and `Operation`, which implement expression tree nodes for constants, variable references, and arithmetic operations. (This example is similar to, but not to be confused with the expression tree types). -:::code language="csharp" source="./Snippets/classes-and-objects/Expressions.cs" id="WorkingWithExpressions"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="WorkingWithExpressions"::: The previous four classes can be used to model arithmetic expressions. For example, using instances of these classes, the expression `x + 3` can be represented as follows. -:::code language="csharp" source="./Snippets/classes-and-objects/Program.cs" id="UseExpressions"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="UseExpressions"::: The `Evaluate` method of an `Expression` instance is invoked to evaluate the given expression and produce a `double` value. The method takes a `Dictionary` argument that contains variable names (as keys of the entries) and values (as values of the entries). Because `Evaluate` is an abstract method, non-abstract classes derived from `Expression` must override `Evaluate`. @@ -143,13 +143,13 @@ A `Constant`'s implementation of `Evaluate` simply returns the stored constant. The following program uses the `Expression` classes to evaluate the expression `x * (y + 2)` for different values of `x` and `y`. -:::code language="csharp" source="./Snippets/classes-and-objects/Expressions.cs" id="UsingExpressions"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="UsingExpressions"::: ### Method overloading Method *overloading* permits multiple methods in the same class to have the same name as long as they have unique signatures. When compiling an invocation of an overloaded method, the compiler uses *overload resolution* to determine the specific method to invoke. Overload resolution finds the one method that best matches the arguments or reports an error if no single best match can be found. The following example shows overload resolution in effect. The comment for each invocation in the `UsageExample` method shows which method is invoked. -:::code language="csharp" source="./Snippets/classes-and-objects/Overloading.cs" id="Overloading"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="Overloading"::: As shown by the example, a particular method can always be selected by explicitly casting the arguments to the exact parameter types and/or explicitly supplying type arguments. @@ -162,7 +162,7 @@ The following example shows a generic class called `MyList`, which implements > [!NOTE] > This example creates a `MyList` class, which is not the same as the .NET standard . It does illustrate the concepts needed for this tour, but is not a replacement for that class. -:::code language="csharp" source="./Snippets/classes-and-objects/ListBasedExamples.cs" id="ListExample"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="ListExample"::: ### Constructors @@ -172,7 +172,7 @@ A constructor is declared like a method with no return type and the same name as Instance constructors can be overloaded and can have optional parameters. For example, the `MyList` class declares one instance constructor with a single optional `int` parameter. Instance constructors are invoked using the `new` operator. The following statements allocate two `MyList` instances using the constructor of the `MyList` class with and without the optional argument. -:::code language="csharp" source="./Snippets/classes-and-objects/ListBasedExamples.cs" id="CreateLists"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="CreateLists"::: Unlike other members, instance constructors aren't inherited, and a class has no instance constructors other than those constructors actually declared in the class. If no instance constructor is supplied for a class, then an empty one with no parameters is automatically provided. @@ -188,7 +188,7 @@ A set accessor corresponds to a method with a single parameter named value and n The `MyList` class declares two properties, `Count` and `Capacity`, which are read-only and read-write, respectively. The following code is an example of use of these properties: -:::code language="csharp" source="./Snippets/classes-and-objects/ListBasedExamples.cs" id="AccessProperties"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="AccessProperties"::: Similar to fields and methods, C# supports both instance properties and static properties. Static properties are declared with the static modifier, and instance properties are declared without it. @@ -200,7 +200,7 @@ An *indexer* is a member that enables objects to be indexed in the same way as a The `MyList` class declares a single read-write indexer that takes an `int` parameter. The indexer makes it possible to index `MyList` instances with `int` values. For example: -:::code language="csharp" source="./Snippets/classes-and-objects/ListBasedExamples.cs" id="ListAddition"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="ListAddition"::: Indexers can be overloaded, meaning that a class can declare multiple indexers as long as the number or types of their parameters differ. @@ -214,7 +214,7 @@ The `MyList` class declares a single event member called `Changed`, which ind Clients react to events through *event handlers*. Event handlers are attached using the `+=` operator and removed using the `-=` operator. The following example attaches an event handler to the `Changed` event of a `MyList`. -:::code language="csharp" source="./Snippets/classes-and-objects/ListBasedExamples.cs" id="RespondToEvents"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="RespondToEvents"::: For advanced scenarios where control of the underlying storage of an event is desired, an event declaration can explicitly provide `add` and `remove` accessors, which are similar to the `set` accessor of a property. @@ -224,7 +224,7 @@ An *operator* is a member that defines the meaning of applying a particular expr The `MyList` class declares two operators, `operator ==` and `operator !=`, and thus gives new meaning to expressions that apply those operators to `MyList` instances. Specifically, the operators define equality of two `MyList` instances as comparing each of the contained objects using their Equals methods. The following example uses the `==` operator to compare two `MyList` instances. -:::code language="csharp" source="./Snippets/classes-and-objects/ListBasedExamples.cs" id="ListAccess"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="ListAccess"::: The first `Console.WriteLine` outputs `True` because the two lists contain the same number of objects with the same values in the same order. Had `MyList` not defined `operator ==`, the first `Console.WriteLine` would have output `False` because `a` and `b` reference different `MyList` instances. diff --git a/docs/csharp/tour-of-csharp/Snippets/program-structure/Program.cs b/docs/csharp/tour-of-csharp/snippets/shared/AcmeStack.cs similarity index 50% rename from docs/csharp/tour-of-csharp/Snippets/program-structure/Program.cs rename to docs/csharp/tour-of-csharp/snippets/shared/AcmeStack.cs index e3a8af4b6a210..1c045830d105e 100644 --- a/docs/csharp/tour-of-csharp/Snippets/program-structure/Program.cs +++ b/docs/csharp/tour-of-csharp/snippets/shared/AcmeStack.cs @@ -1,5 +1,4 @@ -// -using System; +using System; namespace Acme.Collections { public class Stack @@ -33,25 +32,3 @@ public Entry(Entry next, T data) } } } -// - -namespace StackExample -{ - // - using System; - using Acme.Collections; - class Example - { - static void Main() - { - Stack s = new Stack(); - s.Push(1); // stack contains 1 - s.Push(10); // stack contains 1, 10 - s.Push(100); // stack contains 1, 10, 100 - Console.WriteLine(s.Pop()); // stack contains 1, 10 - Console.WriteLine(s.Pop()); // stack contains 1 - Console.WriteLine(s.Pop()); // stack is empty - } - } - // -} diff --git a/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs b/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs new file mode 100644 index 0000000000000..fd3c85843d63f --- /dev/null +++ b/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs @@ -0,0 +1,455 @@ +using System; +using System.Collections.Generic; + +namespace Snippets +{ + // + public class Console + { + public static void Write(string fmt, params object[] args) { } + public static void WriteLine(string fmt, params object[] args) { } + // ... + } + // +} + +namespace TourOfCsharp +{ + // + public class Color + { + public static readonly Color Black = new Color(0, 0, 0); + public static readonly Color White = new Color(255, 255, 255); + public static readonly Color Red = new Color(255, 0, 0); + public static readonly Color Green = new Color(0, 255, 0); + public static readonly Color Blue = new Color(0, 0, 255); + private byte r, g, b; + public Color(byte r, byte g, byte b) + { + this.r = r; + this.g = g; + this.b = b; + } + } + // + + // + class Squares + { + public static void WriteSquares() + { + int i = 0; + int j; + while (i < 10) + { + j = i * i; + Console.WriteLine($"{i} x {i} = {j}"); + i = i + 1; + } + } + } + // + + // + class Entity + { + static int nextSerialNo; + int serialNo; + public Entity() + { + serialNo = nextSerialNo++; + } + public int GetSerialNo() + { + return serialNo; + } + public static int GetNextSerialNo() + { + return nextSerialNo; + } + public static void SetNextSerialNo(int value) + { + nextSerialNo = value; + } + } + // + + // + using System; + using System.Collections.Generic; + public abstract class Expression + { + public abstract double Evaluate(Dictionary vars); + } + public class Constant : Expression + { + double value; + public Constant(double value) + { + this.value = value; + } + public override double Evaluate(Dictionary vars) + { + return value; + } + } + public class VariableReference : Expression + { + string name; + public VariableReference(string name) + { + this.name = name; + } + public override double Evaluate(Dictionary vars) + { + object value = vars[name]; + if (value == null) + { + throw new Exception("Unknown variable: " + name); + } + return Convert.ToDouble(value); + } + } + public class Operation : Expression + { + Expression left; + char op; + Expression right; + public Operation(Expression left, char op, Expression right) + { + this.left = left; + this.op = op; + this.right = right; + } + public override double Evaluate(Dictionary vars) + { + double x = left.Evaluate(vars); + double y = right.Evaluate(vars); + switch (op) + { + case '+': return x + y; + case '-': return x - y; + case '*': return x * y; + case '/': return x / y; + } + throw new Exception("Unknown operator"); + } + } + // + + // + class OverloadingExample + { + static void F() + { + Console.WriteLine("F()"); + } + static void F(object x) + { + Console.WriteLine("F(object)"); + } + static void F(int x) + { + Console.WriteLine("F(int)"); + } + static void F(double x) + { + Console.WriteLine("F(double)"); + } + static void F(T x) + { + Console.WriteLine("F(T)"); + } + static void F(double x, double y) + { + Console.WriteLine("F(double, double)"); + } + public static void UsageExample() + { + F(); // Invokes F() + F(1); // Invokes F(int) + F(1.0); // Invokes F(double) + F("abc"); // Invokes F(string) + F((double)1); // Invokes F(double) + F((object)1); // Invokes F(object) + F(1); // Invokes F(int) + F(1, 1); // Invokes F(double, double) + } + // + } + + // + public class MyList + { + // Constant + const int defaultCapacity = 4; + + // Fields + T[] items; + int count; + + // Constructor + public MyList(int capacity = defaultCapacity) + { + items = new T[capacity]; + } + + // Properties + public int Count => count; + + public int Capacity + { + get { return items.Length; } + set + { + if (value < count) value = count; + if (value != items.Length) + { + T[] newItems = new T[value]; + Array.Copy(items, 0, newItems, 0, count); + items = newItems; + } + } + } + + // Indexer + public T this[int index] + { + get + { + return items[index]; + } + set + { + items[index] = value; + OnChanged(); + } + } + + // Methods + public void Add(T item) + { + if (count == Capacity) Capacity = count * 2; + items[count] = item; + count++; + OnChanged(); + } + protected virtual void OnChanged() => + Changed?.Invoke(this, EventArgs.Empty); + + public override bool Equals(object other) => + Equals(this, other as MyList); + + static bool Equals(MyList a, MyList b) + { + if (Object.ReferenceEquals(a, null)) return Object.ReferenceEquals(b, null); + if (Object.ReferenceEquals(b, null) || a.count != b.count) + return false; + for (int i = 0; i < a.count; i++) + { + if (!object.Equals(a.items[i], b.items[i])) + { + return false; + } + } + return true; + } + + // Event + public event EventHandler Changed; + + // Operators + public static bool operator ==(MyList a, MyList b) => + Equals(a, b); + + public static bool operator !=(MyList a, MyList b) => + !Equals(a, b); + } + // + + // + class EventExample + { + static int changeCount; + static void ListChanged(object sender, EventArgs e) + { + changeCount++; + } + public static void Usage() + { + MyList names = new MyList(); + names.Changed += new EventHandler(ListChanged); + names.Add("Liz"); + names.Add("Martha"); + names.Add("Beth"); + Console.WriteLine(changeCount); // Outputs "3" + } + } + // + + + class ClassesObjects + { + // + static void Swap(ref int x, ref int y) + { + int temp = x; + x = y; + y = temp; + } + public static void SwapExample() + { + int i = 1, j = 2; + Swap(ref i, ref j); + Console.WriteLine($"{i} {j}"); // Outputs "2 1" + } + // + + // + static void Divide(int x, int y, out int result, out int remainder) + { + result = x / y; + remainder = x % y; + } + public static void OutUsage() + { + Divide(10, 3, out int res, out int rem); + Console.WriteLine($"{res} {rem}"); // Outputs "3 1" + } + // + + private static void UseParamArgs() + { + // + int x, y, z; + x = 3; + y = 4; + z = 5; + Console.WriteLine("x={0} y={1} z={2}", x, y, z); + // + } + + + private static void CompilerParams() + { + // + int x = 3, y = 4, z = 5; + + string s = "x={0} y={1} z={2}"; + object[] args = new object[3]; + args[0] = x; + args[1] = y; + args[2] = z; + Console.WriteLine(s, args); + // + } + + private static void UsingEntity() + { + // + Entity.SetNextSerialNo(1000); + Entity e1 = new Entity(); + Entity e2 = new Entity(); + Console.WriteLine(e1.GetSerialNo()); // Outputs "1000" + Console.WriteLine(e2.GetSerialNo()); // Outputs "1001" + Console.WriteLine(Entity.GetNextSerialNo()); // Outputs "1002" + // + } + + private static void UseExpressions() + { + // + Expression e = new Operation( + new VariableReference("x"), + '+', + new Constant(3)); + // + } + + private static void UsingExpressions() + { + // + Expression e = new Operation( + new VariableReference("x"), + '*', + new Operation( + new VariableReference("y"), + '+', + new Constant(2) + ) + ); + Dictionary vars = new Dictionary(); + vars["x"] = 3; + vars["y"] = 5; + Console.WriteLine(e.Evaluate(vars)); // Outputs "21" + vars["x"] = 1.5; + vars["y"] = 9; + Console.WriteLine(e.Evaluate(vars)); // Outputs "16.5" + // + } + + private static void ListExampleOne() + { + // + MyList list1 = new MyList(); + MyList list2 = new MyList(10); + // + + // + MyList names = new MyList(); + names.Capacity = 100; // Invokes set accessor + int i = names.Count; // Invokes get accessor + int j = names.Capacity; // Invokes get accessor + // + } + + private static void ListAddition() + { + // + MyList a = new MyList(); + a.Add(1); + a.Add(2); + MyList b = new MyList(); + b.Add(1); + b.Add(2); + Console.WriteLine(a == b); // Outputs "True" + b.Add(3); + Console.WriteLine(a == b); // Outputs "False" + // + } + + private static void ListAccess() + { + // + MyList names = new MyList(); + names.Add("Liz"); + names.Add("Martha"); + names.Add("Beth"); + for (int i = 0; i < names.Count; i++) + { + string s = names[i]; + names[i] = s.ToUpper(); + } + // + } + + + public static void Examples() + { + SwapExample(); + OutUsage(); + UseParamArgs(); + CompilerParams(); + UsingEntity(); + UseExpressions(); + UsingExpressions(); + + ListExampleOne(); + ListAddition(); + EventExample.Usage(); + ListAccess(); + + } + + } +} diff --git a/docs/csharp/tour-of-csharp/snippets/shared/Features.cs b/docs/csharp/tour-of-csharp/snippets/shared/Features.cs new file mode 100644 index 0000000000000..3c7cda1db91ee --- /dev/null +++ b/docs/csharp/tour-of-csharp/snippets/shared/Features.cs @@ -0,0 +1,202 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; + +namespace TourOfCsharp +{ + + // + delegate double Function(double x); + class Multiplier + { + double factor; + public Multiplier(double factor) + { + this.factor = factor; + } + public double Multiply(double x) + { + return x * factor; + } + } + class DelegateExample + { + static double[] Apply(double[] a, Function f) + { + double[] result = new double[a.Length]; + for (int i = 0; i < a.Length; i++) result[i] = f(a[i]); + return result; + } + public static void Main() + { + double[] a = { 0.0, 0.5, 1.0 }; + double[] squares = Apply(a, (x) => x * x); + double[] sines = Apply(a, Math.Sin); + Multiplier m = new Multiplier(2.0); + double[] doubles = Apply(a, m.Multiply); + } + } + // + + // + public class HelpAttribute : Attribute + { + string url; + string topic; + public HelpAttribute(string url) + { + this.url = url; + } + + public string Url => url; + + public string Topic + { + get { return topic; } + set { topic = value; } + } + } + // + + // + [Help("https://docs.microsoft.com/dotnet/csharp/tour-of-csharp/attributes")] + public class Widget + { + [Help("https://docs.microsoft.com/dotnet/csharp/tour-of-csharp/attributes", + Topic = "Display")] + public void Display(string text) { } + } + // + + + class Features + { + public static void Examples() + { + ArraysSamples(); + DeclareArrays(); + ArrayOfArrays(); + InitializeArray(); + + var weatherData = (Date: DateTime.Now, LowTemp: 5, HighTemp: 30); + // + Console.WriteLine($"The low and high temperature on {weatherData.Date:MM-DD-YYYY} was {weatherData.LowTemp} and {weatherData.HighTemp}"); + // + DelegateExample.Main(); + + ReadAttributes(); + + } + + // + public async Task RetrieveDocsHomePage() + { + var client = new HttpClient(); + byte[] content = await client.GetByteArrayAsync("https://docs.microsoft.com/en-us/"); + + Console.WriteLine($"{nameof(RetrieveDocsHomePage)}: Finished downloading."); + return content.Length; + } + // + + + private static void ReadAttributes() + { + // + Type widgetType = typeof(Widget); + + //Gets every HelpAttribute defined for the Widget type + object[] widgetClassAttributes = widgetType.GetCustomAttributes(typeof(HelpAttribute), false); + + if (widgetClassAttributes.Length > 0) + { + HelpAttribute attr = (HelpAttribute)widgetClassAttributes[0]; + Console.WriteLine($"Widget class help URL : {attr.Url} - Related topic : {attr.Topic}"); + } + + System.Reflection.MethodInfo displayMethod = widgetType.GetMethod(nameof(Widget.Display)); + + //Gets every HelpAttribute defined for the Widget.Display method + object[] displayMethodAttributes = displayMethod.GetCustomAttributes(typeof(HelpAttribute), false); + + if (displayMethodAttributes.Length > 0) + { + HelpAttribute attr = (HelpAttribute)displayMethodAttributes[0]; + Console.WriteLine($"Display method help URL : {attr.Url} - Related topic : {attr.Topic}"); + } + // + } + + static void ApplyDelegate() + { + double[] a = { 0.0, 0.5, 1.0 }; + // + double[] doubles = Apply(a, (double x) => x * 2.0); + // + } + + + private static void InitializeArray() + { + { + // + int[] a = new int[] { 1, 2, 3 }; + // + } + { + // + int[] a = { 1, 2, 3 }; + // + } + // + int[] t = new int[3]; + t[0] = 1; + t[1] = 2; + t[2] = 3; + int[] a = t; + // + + // + foreach (int item in a) + { + Console.WriteLine(item); + } + // + + } + + private static void ArrayOfArrays() + { + // + int[][] a = new int[3][]; + a[0] = new int[10]; + a[1] = new int[5]; + a[2] = new int[20]; + // + } + + private static void DeclareArrays() + { + // + int[] a1 = new int[10]; + int[,] a2 = new int[10, 5]; + int[,,] a3 = new int[10, 5, 2]; + // + } + + private static void ArraysSamples() + { + // + int[] a = new int[10]; + for (int i = 0; i < a.Length; i++) + { + a[i] = i * i; + } + for (int i = 0; i < a.Length; i++) + { + Console.WriteLine($"a[{i}] = {a[i]}"); + } + // + } + } +} diff --git a/docs/csharp/tour-of-csharp/Snippets/hello/Program.cs b/docs/csharp/tour-of-csharp/snippets/shared/HelloWorld.cs similarity index 100% rename from docs/csharp/tour-of-csharp/Snippets/hello/Program.cs rename to docs/csharp/tour-of-csharp/snippets/shared/HelloWorld.cs diff --git a/docs/csharp/tour-of-csharp/snippets/shared/Program.cs b/docs/csharp/tour-of-csharp/snippets/shared/Program.cs new file mode 100644 index 0000000000000..be291cd9a0607 --- /dev/null +++ b/docs/csharp/tour-of-csharp/snippets/shared/Program.cs @@ -0,0 +1,14 @@ +namespace TourOfCsharp +{ + class Program + { + static void Main(string[] args) + { + global::Example.Main(); + + Types.Examples(); + ClassesObjects.Examples(); + Features.Examples(); + } + } +} diff --git a/docs/csharp/tour-of-csharp/snippets/shared/StackUsage.cs b/docs/csharp/tour-of-csharp/snippets/shared/StackUsage.cs new file mode 100644 index 0000000000000..9a721271bb906 --- /dev/null +++ b/docs/csharp/tour-of-csharp/snippets/shared/StackUsage.cs @@ -0,0 +1,15 @@ +using System; +using Acme.Collections; +class Example +{ + public static void Main() + { + Stack s = new Stack(); + s.Push(1); // stack contains 1 + s.Push(10); // stack contains 1, 10 + s.Push(100); // stack contains 1, 10, 100 + Console.WriteLine(s.Pop()); // stack contains 1, 10 + Console.WriteLine(s.Pop()); // stack contains 1 + Console.WriteLine(s.Pop()); // stack is empty + } +} diff --git a/docs/csharp/tour-of-csharp/Snippets/attributes/attributes.csproj b/docs/csharp/tour-of-csharp/snippets/shared/TourOfCsharp.csproj similarity index 60% rename from docs/csharp/tour-of-csharp/Snippets/attributes/attributes.csproj rename to docs/csharp/tour-of-csharp/snippets/shared/TourOfCsharp.csproj index 9acff6d2afa81..5f1457441d0b3 100644 --- a/docs/csharp/tour-of-csharp/Snippets/attributes/attributes.csproj +++ b/docs/csharp/tour-of-csharp/snippets/shared/TourOfCsharp.csproj @@ -1,8 +1,9 @@ - + Exe netcoreapp3.1 + TourOfCsharp.Program diff --git a/docs/csharp/tour-of-csharp/snippets/shared/Types.cs b/docs/csharp/tour-of-csharp/snippets/shared/Types.cs new file mode 100644 index 0000000000000..2163fa269d0b5 --- /dev/null +++ b/docs/csharp/tour-of-csharp/snippets/shared/Types.cs @@ -0,0 +1,151 @@ +using System; +using System.Reflection; + +namespace DeclareTypes +{ + // + public struct Point + { + public double X { get; } + public double Y { get; } + public Point(double x, double y) => (X, Y) = (x, y); + } + // +} +namespace TourOfCsharp +{ + // + public class Point + { + public int x, y; + public Point(int x, int y) + { + this.x = x; + this.y = y; + } + } + // + + // + public class Pair + { + public TFirst First; + public TSecond Second; + } + // + + // + public class Point3D : Point + { + public int z; + public Point3D(int x, int y, int z) : + base(x, y) + { + this.z = z; + } + } + // + + // + interface IControl + { + void Paint(); + } + interface ITextBox : IControl + { + void SetText(string text); + } + interface IListBox : IControl + { + void SetItems(string[] items); + } + interface IComboBox : ITextBox, IListBox { } + // + + // + interface IDataBound + { + void Bind(Binder b); + } + public class EditBox : IControl, IDataBound + { + public void Paint() { } + public void Bind(Binder b) { } + } + // + + // + // A traditional enumeration of some root vegetables. + public enum SomeRootVegetables + { + HorseRadish, + Radish, + Turnip + } + // + + // + // A bit field or flag enumeration of harvesting seasons. + [Flags] + public enum Seasons + { + None = 0, + Summer = 1, + Autumn = 2, + Winter = 4, + Spring = 8, + All = Summer | Autumn | Winter | Spring + } + // + + + public static class Types + { + public static void Examples() + { + // + Point p1 = new Point(0, 0); + Point p2 = new Point(10, 20); + // + + // + Pair pair = new Pair { First = 1, Second = "two" }; + int i = pair.First; // TFirst is int + string s = pair.Second; // TSecond is string + // + + // + Point a = new Point(10, 20); + Point b = new Point3D(10, 20, 30); + // + + // + EditBox editBox = new EditBox(); + IControl control = editBox; + IDataBound dataBound = editBox; + // + + // + var turnip = SomeRootVegetables.Turnip; + + var spring = Seasons.Spring; + var startingOnEquinox = Seasons.Spring | Seasons.Autumn; + var theYear = Seasons.All; + // + + // + int? optionalInt = default; + optionalInt = 5; + string? optionalText = default; + optionalText = "Hello World."; + // + + // + (double Sum, int Count) t2 = (4.5, 3); + Console.WriteLine($"Sum of {t2.Count} elements is {t2.Sum}."); + // Output: + // Sum of 3 elements is 4.5. + // + } + } +} diff --git a/docs/csharp/tour-of-csharp/types.md b/docs/csharp/tour-of-csharp/types.md index ddb8df13c97e9..ab48df60fd353 100644 --- a/docs/csharp/tour-of-csharp/types.md +++ b/docs/csharp/tour-of-csharp/types.md @@ -13,11 +13,11 @@ New classes are created using class declarations. A class declaration starts wit The following code shows a declaration of a simple class named `Point`: -:::code language="csharp" source="./Snippets/classes-and-objects/Point.cs" id="PointClass"::: +:::code language="csharp" source="./snippets/shared/Types.cs" id="PointClass"::: Instances of classes are created using the `new` operator, which allocates memory for a new instance, invokes a constructor to initialize the instance, and returns a reference to the instance. The following statements create two Point objects and store references to those objects in two variables: -:::code language="csharp" source="./Snippets/classes-and-objects/Program.cs" id="CreatePoints"::: +:::code language="csharp" source="./snippets/shared/Types.cs" id="CreatePoints"::: The memory occupied by an object is automatically reclaimed when the object is no longer reachable. It's neither necessary nor possible to explicitly deallocate objects in C#. @@ -25,12 +25,12 @@ The memory occupied by an object is automatically reclaimed when the object is n A class definition may specify a set of type parameters by following the class name with angle brackets enclosing a list of type parameter names. The type parameters can then be used in the body of the class declarations to define the members of the class. In the following example, the type parameters of `Pair` are `TFirst` and `TSecond`: -:::code language="csharp" source="./Snippets/classes-and-objects/Pair.cs" id="DefinePairClass"::: +:::code language="csharp" source="./snippets/shared/Types.cs" id="DefinePairClass"::: A class type that is declared to take type parameters is called a *generic class type*. Struct, interface, and delegate types can also be generic. When the generic class is used, type arguments must be provided for each of the type parameters: -:::code language="csharp" source="./Snippets/classes-and-objects/Program.cs" id="CreatePairObject"::: +:::code language="csharp" source="./snippets/shared/Types.cs" id="CreatePairObject"::: A generic type with type arguments provided, like `Pair` above, is called a *constructed type*. @@ -38,19 +38,19 @@ A generic type with type arguments provided, like `Pair` above, is c A class declaration may specify a base class by following the class name and type parameters with a colon and the name of the base class. Omitting a base class specification is the same as deriving from type `object`. In the following example, the base class of `Point3D` is `Point`. From the first example, the base class of `Point` is `object`: -:::code language="csharp" source="./Snippets/classes-and-objects/Point.cs" id="Create3DPoint"::: +:::code language="csharp" source="./snippets/shared/Types.cs" id="Create3DPoint"::: A class inherits the members of its base class. Inheritance means that a class implicitly contains all members of its base class, except for the instance and static constructors, and the finalizers of the base class. A derived class can add new members to those members it inherits, but it can't remove the definition of an inherited member. In the previous example, `Point3D` inherits the `x` and `y` fields from `Point`, and every `Point3D` instance contains three fields, `x`, `y`, and `z`. An implicit conversion exists from a class type to any of its base class types. A variable of a class type can reference an instance of that class or an instance of any derived class. For example, given the previous class declarations, a variable of type `Point` can reference either a `Point` or a `Point3D`: -:::code language="csharp" source="./Snippets/classes-and-objects/Program.cs" id="ImplicitCastToBase"::: +:::code language="csharp" source="./snippets/shared/Types.cs" id="ImplicitCastToBase"::: ## Structs Classes define types that support inheritance and polymorphism. They enable you to create sophisticated behaviors based on hierarchies of derived classes. By contrast, ***struct*** types are simpler types whose primary purpose is to store data values. Structs cannot declare a base type; they implicitly derive from . You cannot derive other `struct` types from a `struct` type. They are implicitly sealed. -:::code language="csharp" source="./Snippets/classes-and-objects/Point.cs" id="PointStruct"::: +:::code language="csharp" source="./snippets/shared/Types.cs" id="PointStruct"::: ## Interfaces @@ -58,44 +58,41 @@ An ***interface*** defines a contract that can be implemented by classes and str Interfaces may employ ***multiple inheritance***. In the following example, the interface `IComboBox` inherits from both `ITextBox` and `IListBox`. -:::code language="csharp" source="./Snippets/interfaces/Program.cs" id="FirstInterfaces"::: +:::code language="csharp" source="./snippets/shared/Types.cs" id="FirstInterfaces"::: Classes and structs can implement multiple interfaces. In the following example, the class `EditBox` implements both `IControl` and `IDataBound`. -:::code language="csharp" source="./Snippets/interfaces/Program.cs" id="ImplementInterfaces"::: +:::code language="csharp" source="./snippets/shared/Types.cs" id="ImplementInterfaces"::: When a class or struct implements a particular interface, instances of that class or struct can be implicitly converted to that interface type. For example -:::code language="csharp" source="./Snippets/interfaces/Program.cs" id="UseInterfaces"::: +:::code language="csharp" source="./snippets/shared/Types.cs" id="UseInterfaces"::: ## Enums An ***Enum*** type defines a set of constant values. The following `enum` declares constants that define different root vegetables: -:::code language="csharp" source="./Snippets/types-and-variables/Program.cs" id="EnumDeclaration"::: +:::code language="csharp" source="./snippets/shared/Types.cs" id="EnumDeclaration"::: You can also define an `enum` be used in combination as flags. THe following declaration declares a set of flags for the four seasons. Any combination of the seasons may be applied, including an `All` value that includes all seasons: -:::code language="csharp" source="./Snippets/types-and-variables/Program.cs" id="FlagsEnumDeclaration"::: +:::code language="csharp" source="./snippets/shared/Types.cs" id="FlagsEnumDeclaration"::: The following example shows declarations of both the preceding enums: -:::code language="csharp" source="./Snippets/types-and-variables/Program.cs" id="UsingEnums"::: +:::code language="csharp" source="./snippets/shared/Types.cs" id="UsingEnums"::: ## Nullable types -Variables of any type may be declared as ***non-nullable*** or ***nullable***. A nullable variable can hold an additional `null` value, indicating no value. Nullable Value types (structs or enums) are represented by . Non-nullable and Nullable Reference types are both represented by the underlying reference type. The distinction is represented by metadata read by the compiler and some libraries. The compiler provides warnings when nullable references are de-referenced without first checking their value against `null`. The compiler also provides warnings when non-nullable references are assigned to a value that may be `null`. +Variables of any type may be declared as ***non-nullable*** or ***nullable***. A nullable variable can hold an additional `null` value, indicating no value. Nullable Value types (structs or enums) are represented by . Non-nullable and Nullable Reference types are both represented by the underlying reference type. The distinction is represented by metadata read by the compiler and some libraries. The compiler provides warnings when nullable references are de-referenced without first checking their value against `null`. The compiler also provides warnings when non-nullable references are assigned to a value that may be `null`. The following example declares a ***nullable int***, initializing it to `null`. Then, it sets the value to `5`. It demonstrates the same concept with a ***nullable string***. + +:::code language="csharp" source="./snippets/shared/Types.cs" id="DeclareNullable"::: ## Tuples C# supports ***tuples*** which provides concise syntax to group multiple data elements in a lightweight data structure. You instantiate a tuple by declaring the types and names of the members between `(` and `)`, as shown in the following example: -```csharp -(double Sum, int Count) t2 = (4.5, 3); -Console.WriteLine($"Sum of {t2.Count} elements is {t2.Sum}."); -// Output: -// Sum of 3 elements is 4.5. -``` +:::code language="csharp" source="./snippets/shared/Types.cs" id="DeclareTuples"::: Tuples provide an alternative when you want a data structure for multiple members, but won't use the building blocks described in the next article. From 368aa1324db70383423a7e4bac086aadf3986a1c Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 6 Aug 2020 15:35:57 -0400 Subject: [PATCH 03/11] grammar check --- docs/csharp/tour-of-csharp/features.md | 46 +++++------ docs/csharp/tour-of-csharp/index.md | 16 ++-- .../tour-of-csharp/program-building-blocks.md | 80 +++++++++---------- .../snippets/shared/ClassesObjects.cs | 2 - docs/csharp/tour-of-csharp/types.md | 57 +++++++------ 5 files changed, 103 insertions(+), 98 deletions(-) diff --git a/docs/csharp/tour-of-csharp/features.md b/docs/csharp/tour-of-csharp/features.md index 6b7f3183ec1e8..d4d7c5d3cf74d 100644 --- a/docs/csharp/tour-of-csharp/features.md +++ b/docs/csharp/tour-of-csharp/features.md @@ -1,50 +1,50 @@ --- title: A Tour of C# - C# Guide description: New to C#? Learn the basics of the language. -ms.date: 08/03/2020 +ms.date: 08/06/2020 --- # Major features -## Arrays, collections and LINQ +## Arrays, collections, and LINQ -C# and .NET provide many different collection types. Arrays have syntax defined by the language. General collection types are listed in the namespace. Specialized collections include for accessing continuous memory on the stack frame, and for accessing continuous memory on the managed heap. All collections, including arrays, and share a unifying principle for iteration. You use the interface. This unifying principle means that any of the collection types can be used with LINQ queries or other algorithms. You write methods using and those algorithms work with any collection. +C# and .NET provide many different collection types. Arrays have syntax defined by the language. General collection types are listed in the namespace. Specialized collections include for accessing continuous memory on the stack frame, and for accessing continuous memory on the managed heap. All collections, including arrays, , and share a unifying principle for iteration. You use the interface. This unifying principle means that any of the collection types can be used with LINQ queries or other algorithms. You write methods using and those algorithms work with any collection. ### Arrays -An ***array*** is a data structure that contains a number of variables that are accessed through computed indices. The variables contained in an array, also called the ***elements*** of the array, are all of the same type, and this type is called the ***element type*** of the array. +An ***array*** is a data structure that contains a number of variables that are accessed through computed indices. The variables contained in an array, also called the ***elements*** of the array, are all of the same type. This type is called the ***element type*** of the array. Array types are reference types, and the declaration of an array variable simply sets aside space for a reference to an array instance. Actual array instances are created dynamically at runtime using the new operator. The new operation specifies the ***length*** of the new array instance, which is then fixed for the lifetime of the instance. The indices of the elements of an array range from `0` to `Length - 1`. The `new` operator automatically initializes the elements of an array to their default value, which, for example, is zero for all numeric types and `null` for all reference types. The following example creates an array of `int` elements, initializes the array, and prints out the contents of the array. -:::code language="csharp" source="./snippets/shared/Features.cs" id="ArraysSample"::: +:::code language="csharp" source="./snippets/shared/Features.cs" ID="ArraysSample"::: This example creates and operates on a ***single-dimensional array***. C# also supports ***multi-dimensional arrays***. The number of dimensions of an array type, also known as the ***rank*** of the array type, is one plus the number of commas written between the square brackets of the array type. The following example allocates a single-dimensional, a two-dimensional, and a three-dimensional array, respectively. -:::code language="csharp" source="./snippets/shared/Features.cs" id="DeclareArrays"::: +:::code language="csharp" source="./snippets/shared/Features.cs" ID="DeclareArrays"::: The `a1` array contains 10 elements, the `a2` array contains 50 (10 × 5) elements, and the `a3` array contains 100 (10 × 5 × 2) elements. The element type of an array can be any type, including an array type. An array with elements of an array type is sometimes called a ***jagged array*** because the lengths of the element arrays don't all have to be the same. The following example allocates an array of arrays of `int`: -:::code language="csharp" source="./snippets/shared/Features.cs" id="ArrayOfArrays"::: +:::code language="csharp" source="./snippets/shared/Features.cs" ID="ArrayOfArrays"::: -The first line creates an array with three elements, each of type `int[]` and each with an initial value of `null`. The subsequent lines then initialize the three elements with references to individual array instances of varying lengths. +The first line creates an array with three elements, each of type `int[]` and each with an initial value of `null`. The next lines then initialize the three elements with references to individual array instances of varying lengths. The new operator permits the initial values of the array elements to be specified using an ***array initializer***, which is a list of expressions written between the delimiters `{` and `}`. The following example allocates and initializes an `int[]` with three elements. -:::code language="csharp" source="./snippets/shared/Features.cs" id="InitializeArray"::: +:::code language="csharp" source="./snippets/shared/Features.cs" ID="InitializeArray"::: -The length of the array is inferred from the number of expressions between { and }. Local variable and field declarations can be shortened further such that the array type does not have to be restated. +The length of the array is inferred from the number of expressions between { and }. Local variable and field declarations can be shortened further such that the array type doesn't have to be restated. -:::code language="csharp" source="./snippets/shared/Features.cs" id="InitializeShortened"::: +:::code language="csharp" source="./snippets/shared/Features.cs" ID="InitializeShortened"::: Both of the previous examples are equivalent to the following code: -:::code language="csharp" source="./snippets/shared/Features.cs" id="InitializeGenerated"::: +:::code language="csharp" source="./snippets/shared/Features.cs" ID="InitializeGenerated"::: The `foreach` statement can be used to enumerate the elements of any collection. The following code enumerates the array from the preceding example: -:::code language="csharp" source="./snippets/shared/Features.cs" id="EnumerateArray"::: +:::code language="csharp" source="./snippets/shared/Features.cs" ID="EnumerateArray"::: The `foreach` statement uses the interface, so can work with any collection. @@ -52,13 +52,13 @@ The `foreach` statement uses the , but can be any type that supports the awaiter pattern. This enables you to write code that reads as its synchronous counterpart, but executes asynchronously. For example, the following code downloads the home page for [Microsoft docs](https://docs.microsoft.com): +C# supports asynchronous programs with two keywords: `async` and `await`. You add the `async` modifier to a method declaration to declare the method is asynchronous. The `aawit` operator tells the compiler that to asynchronously await for a result to finish. Control is returned to the caller, and the method returns a structure that manages the state of the asynchronous work. The structure is typically a , but can be any type that supports the awaiter pattern. These features enable you to write code that reads as its synchronous counterpart, but executes asynchronously. For example, the following code downloads the home page for [Microsoft docs](https://docs.microsoft.com): -:::code language="csharp" source="./snippets/shared/Features.cs" id="AsyncExample"::: +:::code language="csharp" source="./snippets/shared/Features.cs" ID="AsyncExample"::: This small sample shows the major features for asynchronous programming: @@ -96,11 +96,11 @@ Types, members, and other entities in a C# program support modifiers that contro The following example declares a `HelpAttribute` attribute that can be placed on program entities to provide links to their associated documentation. -:::code language="csharp" source="./snippets/shared/Features.cs" id="DefineAttribute"::: +:::code language="csharp" source="./snippets/shared/Features.cs" ID="DefineAttribute"::: All attribute classes derive from the base class provided by the standard library. Attributes can be applied by giving their name, along with any arguments, inside square brackets just before the associated declaration. If an attribute’s name ends in `Attribute`, that part of the name can be omitted when the attribute is referenced. For example, the `HelpAttribute` can be used as follows. -:::code language="csharp" source="./snippets/shared/Features.cs" id="UseAttributes"::: +:::code language="csharp" source="./snippets/shared/Features.cs" ID="UseAttributes"::: This example attaches a `HelpAttribute` to the `Widget` class. It adds another `HelpAttribute` to the `Display` method in the class. The public constructors of an attribute class control the information that must be provided when the attribute is attached to a program entity. Additional information can be provided by referencing public read-write properties of the attribute class (such as the reference to the `Topic` property previously). @@ -108,7 +108,7 @@ The metadata defined by attributes can be read and manipulated at runtime using The following code sample demonstrates how to get the `HelpAttribute` instances associated to the `Widget` class and its `Display` method. -:::code language="csharp" source="./snippets/shared/attributes/Program.cs" id="ReadAttributes"::: +:::code language="csharp" source="./snippets/shared/attributes/Program.cs" ID="ReadAttributes"::: ## Learn more diff --git a/docs/csharp/tour-of-csharp/index.md b/docs/csharp/tour-of-csharp/index.md index 77c3d4c47938d..f222543697835 100644 --- a/docs/csharp/tour-of-csharp/index.md +++ b/docs/csharp/tour-of-csharp/index.md @@ -1,18 +1,18 @@ --- title: A Tour of C# - C# Guide description: New to C#? Learn the basics of the language. -ms.date: 08/03/2020 +ms.date: 08/06/2020 --- # A tour of the C# language C# (pronounced "See Sharp") is a modern, object-oriented, and type-safe programming language. C# has its roots in the C family of languages and will be immediately familiar to C, C++, Java, and JavaScript programmers. This tour provides an overview of the major components of the language in C# 8 and earlier. If you want to explore the language through interactive examples, try the [introduction to C#](../tutorials/intro-to-csharp/index.md) tutorials. -C# is an object-oriented, ***component-oriented*** programming. C# provides language constructs to support directly these concepts, making C# a natural language in which to create and use software components. Since its inception, C# has added features to support new workloads and emerging software design practices. +C# is an object-oriented, ***component-oriented*** programming. C# provides language constructs to support directly these concepts, making C# a natural language in which to create and use software components. Since its origin, C# has added features to support new workloads and emerging software design practices. -Several C# features aid in the construction of robust and durable applications. ***Garbage collection*** automatically reclaims memory occupied by unreachable unused objects. ***Exception handling*** provides a structured and extensible approach to error detection and recovery. ***Lambda expressions*** suppport functional programming techniques. ***Query syntax*** creates a common pattern for working with data from any source. Language support for ***asynchronous operations*** provides syntax for building distributed systems. ***Pattern matching*** provides syntax to easily separate data from algorithms in modern distributed systems. C# has a ***unified type system***. All C# types, including primitive types such as `int` and `double`, inherit from a single root `object` type. Thus, all types share a set of common operations, and values of any type can be stored, transported, and operated upon in a consistent manner. Furthermore, C# supports both user-defined reference types and value types, allowing dynamic allocation of objects as well as in-line storage of lightweight structures. +Several C# features aid in the construction of robust and durable applications. ***Garbage collection*** automatically reclaims memory occupied by unreachable unused objects. ***Exception handling*** provides a structured and extensible approach to error detection and recovery. ***Lambda expressions*** support functional programming techniques. ***Query syntax*** creates a common pattern for working with data from any source. Language support for ***asynchronous operations*** provides syntax for building distributed systems. ***Pattern matching*** provides syntax to easily separate data from algorithms in modern distributed systems. C# has a ***unified type system***. All C# types, including primitive types such as `int` and `double`, inherit from a single root `object` type. All types share a set of common operations. Values of any type can be stored, transported, and operated upon in a consistent manner. Furthermore, C# supports both user-defined reference types and value types. C# allows dynamic allocation of objects and in-line storage of lightweight structures. -To ensure that C# programs and libraries can evolve over time in a compatible manner, much emphasis has been placed on ***versioning*** in C#'s design. Aspects of C#'s design that were directly influenced by versioning considerations include the separate `virtual` and `override` modifiers, the rules for method overload resolution, and support for explicit interface member declarations. +C# emphasizes ***versioning*** to ensure programs and libraries can evolve over time in a compatible manner. Aspects of C#'s design that were directly influenced by versioning considerations include the separate `virtual` and `override` modifiers, the rules for method overload resolution, and support for explicit interface member declarations. ## Hello world @@ -28,7 +28,7 @@ The output of the program is produced by the `WriteLine` method of the `Console` ## Types and variables -There are two kinds of types in C#: *value types* and *reference types*. Variables of value types directly contain their data whereas variables of reference types store references to their data, the latter being known as objects. With reference types, it's possible for two variables to reference the same object and thus possible for operations on one variable to affect the object referenced by the other variable. With value types, the variables each have their own copy of the data, and it isn't possible for operations on one to affect the other (except for `ref` and `out` parameter variables). +There are two kinds of types in C#: *value types* and *reference types*. Variables of value types directly contain their data whereas variables of reference types store references to their data, the latter being known as objects. With reference types, it's possible for two variables to reference the same object and possible for operations on one variable to affect the object referenced by the other variable. With value types, the variables each have their own copy of the data, and it isn't possible for operations on one to affect the other (except for `ref` and `out` parameter variables). C#'s value types are further divided into *simple types*, *enum types*, *struct types*, and *nullable value types*. C#'s reference types are further divided into *class types*, *interface types*, *array types*, and *delegate types*. @@ -73,17 +73,17 @@ The `class`, `struct`, `interface`, and `delegate` types all support generics, w C# supports single- and multi-dimensional arrays of any type. Unlike the types listed above, array types don't have to be declared before they can be used. Instead, array types are constructed by following a type name with square brackets. For example, `int[]` is a single-dimensional array of `int`, `int[,]` is a two-dimensional array of `int`, and `int[][]` is a single-dimensional array of single-dimensional array of `int`. -Nullable value types also don't have to be declared before they can be used. For each non-nullable value type `T`, there is a corresponding nullable value type `T?`, which can hold an additional value, `null`. For instance, `int?` is a type that can hold any 32-bit integer or the value `null`. +Nullable types don't require a separate definition. For each non-nullable type `T`, there's a corresponding nullable type `T?`, which can hold an additional value, `null`. For instance, `int?` is a type that can hold any 32-bit integer or the value `null`, and `string?` is a type that can hold any `string` or the value `null`. C#'s type system is unified such that a value of any type can be treated as an `object`. Every type in C# directly or indirectly derives from the `object` class type, and `object` is the ultimate base class of all types. Values of reference types are treated as objects simply by viewing the values as type `object`. Values of value types are treated as objects by performing *boxing* and *unboxing operations*. In the following example, an `int` value is converted to `object` and back again to `int`. -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/shared/types-and-variables/Program.cs" id="boxing" ::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/shared/types-and-variables/Program.cs" ID="boxing" ::: When a value of a value type is assigned to an `object` reference, a "box" is allocated to hold the value. That box is an instance of a reference type, and the value is copied into that box. Conversely, when an `object` reference is cast to a value type, a check is made that the referenced `object` is a box of the correct value type. If the check succeeds, the value in the box is copied to the value type. C#'s unified type system effectively means that value types are treated as `object` references "on demand." Because of the unification, general-purpose libraries that use type `object` can be used with all types that derive from `object`, including both reference types and value types. -There are several kinds of *variables* in C#, including fields, array elements, local variables, and parameters. Variables represent storage locations, and every variable has a type that determines what values can be stored in the variable, as shown below. +There are several kinds of *variables* in C#, including fields, array elements, local variables, and parameters. Variables represent storage locations. Every variable has a type that determines what values can be stored in the variable, as shown below. - Non-nullable value type - A value of that exact type diff --git a/docs/csharp/tour-of-csharp/program-building-blocks.md b/docs/csharp/tour-of-csharp/program-building-blocks.md index 75691075c7efe..aa0dcb0f1cdf6 100644 --- a/docs/csharp/tour-of-csharp/program-building-blocks.md +++ b/docs/csharp/tour-of-csharp/program-building-blocks.md @@ -1,11 +1,11 @@ --- -title: "The building blocks of of C# programs: Learn about members, expressions and statements." +title: "The building blocks of C# programs: Learn about members, expressions, and statements." description: Types contain members you write. Those members are built from statements and expressions. -ms.date: 08/03/2020 +ms.date: 08/06/2020 --- # Program Building blocks -The types described in the previous article are built using these building blocks: ***members***, ***expressions*** and ***statements***. +The types described in the previous article are built using these building blocks: ***members***, ***expressions, and ***statements***. ## Members @@ -21,7 +21,7 @@ The following list provides an overview of the kinds of members a class can cont - **Events**: Notifications that can be generated by the class - **Operators**: Conversions and expression operators supported by the class - **Constructors**: Actions required to initialize instances of the class or the class itself -- **Finalizers**: Actions to perform before instances of the class are permanently discarded +- **Finalizers**: Actions performed before instances of the class are permanently discarded - **Types**: Nested types declared by the class ## Accessibility @@ -45,7 +45,7 @@ A field declared without the static modifier defines an instance field. Every in In the following example, each instance of the `Color` class has a separate copy of the `r`, `g`, and `b` instance fields, but there's only one copy of the `Black`, `White`, `Red`, `Green`, and `Blue` static fields: -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="ColorClassDefinition"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="ColorClassDefinition"::: As shown in the previous example, *read-only fields* may be declared with a `readonly` modifier. Assignment to a `readonly` field can only occur as part of the field’s declaration or in a constructor in the same class. @@ -53,11 +53,11 @@ As shown in the previous example, *read-only fields* may be declared with a `rea A *method* is a member that implements a computation or action that can be performed by an object or class. *Static methods* are accessed through the class. *Instance methods* are accessed through instances of the class. -Methods may have a list of *parameters*, which represent values or variable references passed to the method, and a *return type*, which specifies the type of the value computed and returned by the method. A method’s return type is `void` if it doesn't return a value. +Methods may have a list of *parameters*, which represent values or variable references passed to the method. Methods have a *return type*, which specifies the type of the value computed and returned by the method. A method’s return type is `void` if it doesn't return a value. Like types, methods may also have a set of type parameters, for which type arguments must be specified when the method is called. Unlike types, the type arguments can often be inferred from the arguments of a method call and need not be explicitly given. -The *signature* of a method must be unique in the class in which the method is declared. The signature of a method consists of the name of the method, the number of type parameters and the number, modifiers, and types of its parameters. The signature of a method doesn't include the return type. +The *signature* of a method must be unique in the class in which the method is declared. The signature of a method consists of the name of the method, the number of type parameters, and the number, modifiers, and types of its parameters. The signature of a method doesn't include the return type. ### Parameters @@ -67,25 +67,25 @@ A *value parameter* is used for passing input arguments. A value parameter corre Value parameters can be optional, by specifying a default value so that corresponding arguments can be omitted. -A *reference parameter* is used for passing arguments by reference. The argument passed for a reference parameter must be a variable with a definite value, and during execution of the method, the reference parameter represents the same storage location as the argument variable. A reference parameter is declared with the `ref` modifier. The following example shows the use of `ref` parameters. +A *reference parameter* is used for passing arguments by reference. The argument passed for a reference parameter must be a variable with a definite value. During execution of the method, the reference parameter represents the same storage location as the argument variable. A reference parameter is declared with the `ref` modifier. The following example shows the use of `ref` parameters. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="RefExample"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="RefExample"::: An *output parameter* is used for passing arguments by reference. It's similar to a reference parameter, except that it doesn't require that you explicitly assign a value to the caller-provided argument. An output parameter is declared with the `out` modifier. The following example shows the use of `out` parameters using the syntax introduced in C# 7. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="OutExample"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="OutExample"::: A *parameter array* permits a variable number of arguments to be passed to a method. A parameter array is declared with the `params` modifier. Only the last parameter of a method can be a parameter array, and the type of a parameter array must be a single-dimensional array type. The Write and WriteLine methods of the class are good examples of parameter array usage. They're declared as follows. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="ConsoleExtract"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="ConsoleExtract"::: Within a method that uses a parameter array, the parameter array behaves exactly like a regular parameter of an array type. However, in an invocation of a method with a parameter array, it's possible to pass either a single argument of the parameter array type or any number of arguments of the element type of the parameter array. In the latter case, an array instance is automatically created and initialized with the given arguments. This example -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="UseParamsArgs"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="UseParamsArgs"::: is equivalent to writing the following. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="CompilerParams"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="CompilerParams"::: ### Method body and local variables @@ -93,9 +93,9 @@ A method’s body specifies the statements to execute when the method is invoked A method body can declare variables that are specific to the invocation of the method. Such variables are called *local variables*. A local variable declaration specifies a type name, a variable name, and possibly an initial value. The following example declares a local variable `i` with an initial value of zero and a local variable `j` with no initial value. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="SquaresClass"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="SquaresClass"::: -C# requires a local variable to be *definitely assigned* before its value can be obtained. For example, if the declaration of the previous `i` didn't include an initial value, the compiler would report an error for the subsequent usages of `i` because `i` wouldn't be definitely assigned at those points in the program. +C# requires a local variable to be *definitely assigned* before its value can be obtained. For example, if the declaration of the previous `i` didn't include an initial value, the compiler would report an error for the later usages of `i` because `i` wouldn't be definitely assigned at those points in the program. A method can use `return` statements to return control to its caller. In a method returning `void`, `return` statements can't specify an expression. In a method returning non-void, `return` statements must include an expression that computes the return value. @@ -107,7 +107,7 @@ A method declared without a static modifier is an *instance method*. An instance The following `Entity` class has both static and instance members. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="EntityClass"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="EntityClass"::: Each `Entity` instance contains a serial number (and presumably some other information that isn't shown here). The `Entity` constructor (which is like an instance method) initializes the new instance with the next available serial number. Because the constructor is an instance member, it's permitted to access both the `serialNo` instance field and the `nextSerialNo` static field. @@ -115,7 +115,7 @@ The `GetNextSerialNo` and `SetNextSerialNo` static methods can access the `nextS The following example shows the use of the Entity class. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="UsingEntity"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="UsingEntity"::: The `SetNextSerialNo` and `GetNextSerialNo` static methods are invoked on the class whereas the `GetSerialNo` instance method is invoked on instances of the class. @@ -125,17 +125,17 @@ When an instance method declaration includes a `virtual` modifier, the method is When a virtual method is invoked, the *run-time type* of the instance for which that invocation takes place determines the actual method implementation to invoke. In a nonvirtual method invocation, the *compile-time type* of the instance is the determining factor. -A virtual method can be *overridden* in a derived class. When an instance method declaration includes an override modifier, the method overrides an inherited virtual method with the same signature. Whereas a virtual method declaration introduces a new method, an override method declaration specializes an existing inherited virtual method by providing a new implementation of that method. +A virtual method can be *overridden* in a derived class. When an instance method declaration includes an override modifier, the method overrides an inherited virtual method with the same signature. Aa virtual method declaration introduces a new method. An override method declaration specializes an existing inherited virtual method by providing a new implementation of that method. -An *abstract method* is a virtual method with no implementation. An abstract method is declared with the abstract modifier and is permitted only in a class that is also declared abstract. An abstract method must be overridden in every non-abstract derived class. +An *abstract method* is a virtual method with no implementation. An abstract method is declared with the `abstract` modifier and is permitted only in an abstract class. An abstract method must be overridden in every non-abstract derived class. The following example declares an abstract class, `Expression`, which represents an expression tree node, and three derived classes, `Constant`, `VariableReference`, and `Operation`, which implement expression tree nodes for constants, variable references, and arithmetic operations. (This example is similar to, but not to be confused with the expression tree types). -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="WorkingWithExpressions"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="WorkingWithExpressions"::: The previous four classes can be used to model arithmetic expressions. For example, using instances of these classes, the expression `x + 3` can be represented as follows. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="UseExpressions"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="UseExpressions"::: The `Evaluate` method of an `Expression` instance is invoked to evaluate the given expression and produce a `double` value. The method takes a `Dictionary` argument that contains variable names (as keys of the entries) and values (as values of the entries). Because `Evaluate` is an abstract method, non-abstract classes derived from `Expression` must override `Evaluate`. @@ -143,15 +143,15 @@ A `Constant`'s implementation of `Evaluate` simply returns the stored constant. The following program uses the `Expression` classes to evaluate the expression `x * (y + 2)` for different values of `x` and `y`. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="UsingExpressions"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="UsingExpressions"::: ### Method overloading -Method *overloading* permits multiple methods in the same class to have the same name as long as they have unique signatures. When compiling an invocation of an overloaded method, the compiler uses *overload resolution* to determine the specific method to invoke. Overload resolution finds the one method that best matches the arguments or reports an error if no single best match can be found. The following example shows overload resolution in effect. The comment for each invocation in the `UsageExample` method shows which method is invoked. +Method *overloading* permits multiple methods in the same class to have the same name as long as they have unique signatures. When compiling an invocation of an overloaded method, the compiler uses *overload resolution* to determine the specific method to invoke. Overload resolution finds the one method that best matches the arguments. If no single best match can be found, an error is reported. The following example shows overload resolution in effect. The comment for each invocation in the `UsageExample` method shows which method is invoked. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="Overloading"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="Overloading"::: -As shown by the example, a particular method can always be selected by explicitly casting the arguments to the exact parameter types and/or explicitly supplying type arguments. +As shown by the example, a particular method can always be selected by explicitly casting the arguments to the exact parameter types and type arguments. ## Other function members @@ -162,7 +162,7 @@ The following example shows a generic class called `MyList`, which implements > [!NOTE] > This example creates a `MyList` class, which is not the same as the .NET standard . It does illustrate the concepts needed for this tour, but is not a replacement for that class. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="ListExample"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="ListExample"::: ### Constructors @@ -172,23 +172,23 @@ A constructor is declared like a method with no return type and the same name as Instance constructors can be overloaded and can have optional parameters. For example, the `MyList` class declares one instance constructor with a single optional `int` parameter. Instance constructors are invoked using the `new` operator. The following statements allocate two `MyList` instances using the constructor of the `MyList` class with and without the optional argument. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="CreateLists"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="CreateLists"::: -Unlike other members, instance constructors aren't inherited, and a class has no instance constructors other than those constructors actually declared in the class. If no instance constructor is supplied for a class, then an empty one with no parameters is automatically provided. +Unlike other members, instance constructors aren't inherited. A class has no instance constructors other than those constructors actually declared in the class. If no instance constructor is supplied for a class, then an empty one with no parameters is automatically provided. ### Properties -*Properties* are a natural extension of fields. Both are named members with associated types, and the syntax for accessing fields and properties is the same. However, unlike fields, properties don't denote storage locations. Instead, properties have *accessors* that specify the statements to be executed when their values are read or written. +*Properties* are a natural extension of fields. Both are named members with associated types, and the syntax for accessing fields and properties is the same. However, unlike fields, properties don't denote storage locations. Instead, properties have *accessors* that specify the statements executed when their values are read or written. -A property is declared like a field, except that the declaration ends with a get accessor and/or a set accessor written between the delimiters `{` and `}` instead of ending in a semicolon. A property that has both a get accessor and a set accessor is a *read-write property*, a property that has only a get accessor is a *read-only property*, and a property that has only a set accessor is a *write-only property*. +A property is declared like a field, except that the declaration ends with a get accessor or a set accessor written between the delimiters `{` and `}` instead of ending in a semicolon. A property that has both a get accessor and a set accessor is a *read-write property*, a property that has only a get accessor is a *read-only property*, and a property that has only a set accessor is a *write-only property*. -A get accessor corresponds to a parameterless method with a return value of the property type. Except as the target of an assignment, when a property is referenced in an expression, the get accessor of the property is invoked to compute the value of the property. +A get accessor corresponds to a parameterless method with a return value of the property type. A set accessor corresponds to a method with a single parameter named value and no return type. The get accessor computes the value of the property. The set accessor provides a new value for the property. When the property is the target of an assignment, or the operand of `++` or `--`, the set accessor is invoked. In other cases where the property is referenced, the get accessor is invoked. -A set accessor corresponds to a method with a single parameter named value and no return type. When a property is referenced as the target of an assignment or as the operand of ++ or --, the set accessor is invoked with an argument that provides the new value. + When a property is referenced as the target of an assignment or as the operand of ++ or --, the set accessor is invoked with an argument that provides the new value. The `MyList` class declares two properties, `Count` and `Capacity`, which are read-only and read-write, respectively. The following code is an example of use of these properties: -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="AccessProperties"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="AccessProperties"::: Similar to fields and methods, C# supports both instance properties and static properties. Static properties are declared with the static modifier, and instance properties are declared without it. @@ -200,21 +200,21 @@ An *indexer* is a member that enables objects to be indexed in the same way as a The `MyList` class declares a single read-write indexer that takes an `int` parameter. The indexer makes it possible to index `MyList` instances with `int` values. For example: -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="ListAddition"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="ListAddition"::: -Indexers can be overloaded, meaning that a class can declare multiple indexers as long as the number or types of their parameters differ. +Indexers can be overloaded. A class can declare multiple indexers as long as the number or types of their parameters differ. ### Events -An *event* is a member that enables a class or object to provide notifications. An event is declared like a field except that the declaration includes an event keyword and the type must be a delegate type. +An *event* is a member that enables a class or object to provide notifications. An event is declared like a field except that the declaration includes an `event` keyword and the type must be a delegate type. Within a class that declares an event member, the event behaves just like a field of a delegate type (provided the event isn't abstract and doesn't declare accessors). The field stores a reference to a delegate that represents the event handlers that have been added to the event. If no event handlers are present, the field is `null`. -The `MyList` class declares a single event member called `Changed`, which indicates that a new item has been added to the list. The Changed event is raised by the `OnChanged` virtual method, which first checks whether the event is `null` (meaning that no handlers are present). The notion of raising an event is precisely equivalent to invoking the delegate represented by the event—thus, there are no special language constructs for raising events. +The `MyList` class declares a single event member called `Changed`, which indicates that a new item has been added to the list. The Changed event is raised by the `OnChanged` virtual method, which first checks whether the event is `null` (meaning that no handlers are present). The notion of raising an event is precisely equivalent to invoking the delegate represented by the event. There are no special language constructs for raising events. Clients react to events through *event handlers*. Event handlers are attached using the `+=` operator and removed using the `-=` operator. The following example attaches an event handler to the `Changed` event of a `MyList`. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="RespondToEvents"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="RespondToEvents"::: For advanced scenarios where control of the underlying storage of an event is desired, an event declaration can explicitly provide `add` and `remove` accessors, which are similar to the `set` accessor of a property. @@ -222,9 +222,9 @@ For advanced scenarios where control of the underlying storage of an event is de An *operator* is a member that defines the meaning of applying a particular expression operator to instances of a class. Three kinds of operators can be defined: unary operators, binary operators, and conversion operators. All operators must be declared as `public` and `static`. -The `MyList` class declares two operators, `operator ==` and `operator !=`, and thus gives new meaning to expressions that apply those operators to `MyList` instances. Specifically, the operators define equality of two `MyList` instances as comparing each of the contained objects using their Equals methods. The following example uses the `==` operator to compare two `MyList` instances. +The `MyList` class declares two operators, `operator ==` and `operator !=`. These overridden opeators give new meaning to expressions that apply those operators to `MyList` instances. Specifically, the operators define equality of two `MyList` instances as comparing each of the contained objects using their Equals methods. The following example uses the `==` operator to compare two `MyList` instances. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" id="ListAccess"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="ListAccess"::: The first `Console.WriteLine` outputs `True` because the two lists contain the same number of objects with the same values in the same order. Had `MyList` not defined `operator ==`, the first `Console.WriteLine` would have output `False` because `a` and `b` reference different `MyList` instances. diff --git a/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs b/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs index fd3c85843d63f..9d8fd40cebee2 100644 --- a/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs +++ b/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs @@ -75,8 +75,6 @@ public static void SetNextSerialNo(int value) // // - using System; - using System.Collections.Generic; public abstract class Expression { public abstract double Evaluate(Dictionary vars); diff --git a/docs/csharp/tour-of-csharp/types.md b/docs/csharp/tour-of-csharp/types.md index ab48df60fd353..05e84524143d4 100644 --- a/docs/csharp/tour-of-csharp/types.md +++ b/docs/csharp/tour-of-csharp/types.md @@ -1,7 +1,7 @@ --- title: Define types and their members - A tour of C# description: The building blocks of programs are types. Learn how to create classes, structs, interfaces, and more in C#. -ms.date: 08/03/2020 +ms.date: 08/06/2020 --- # Types and members @@ -9,48 +9,55 @@ ms.date: 08/03/2020 *Classes* are the most fundamental of C#’s types. A class is a data structure that combines state (fields) and actions (methods and other function members) in a single unit. A class provides a definition for dynamically created *instances* of the class, also known as *objects*. Classes support *inheritance* and *polymorphism*, mechanisms whereby *derived classes* can extend and specialize *base classes*. -New classes are created using class declarations. A class declaration starts with a header that specifies the attributes and modifiers of the class, the name of the class, the base class (if given), and the interfaces implemented by the class. The header is followed by the class body, which consists of a list of member declarations written between the delimiters `{` and `}`. +New classes are created using class declarations. A class declaration starts with a header. The header specifies: + +- The attributes and modifiers of the class +- The name of the class +- The base class (if given) +- The interfaces implemented by the class. +- +- The header is followed by the class body, which consists of a list of member declarations written between the delimiters `{` and `}`. The following code shows a declaration of a simple class named `Point`: -:::code language="csharp" source="./snippets/shared/Types.cs" id="PointClass"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="PointClass"::: -Instances of classes are created using the `new` operator, which allocates memory for a new instance, invokes a constructor to initialize the instance, and returns a reference to the instance. The following statements create two Point objects and store references to those objects in two variables: +Instances of classes are created using the `new` operator, which allocates memory for a new instance, invokes a constructor to initialize the instance, and returns a reference to the instance. The following statements create two `Point` objects and store references to those objects in two variables: -:::code language="csharp" source="./snippets/shared/Types.cs" id="CreatePoints"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="CreatePoints"::: The memory occupied by an object is automatically reclaimed when the object is no longer reachable. It's neither necessary nor possible to explicitly deallocate objects in C#. ### Type parameters -A class definition may specify a set of type parameters by following the class name with angle brackets enclosing a list of type parameter names. The type parameters can then be used in the body of the class declarations to define the members of the class. In the following example, the type parameters of `Pair` are `TFirst` and `TSecond`: +Generic classes define ***type parameters***. Type parameters are a list of type parameters names enclosed in angle brackets. Type parameters follow the class name. The type parameters can then be used in the body of the class declarations to define the members of the class. In the following example, the type parameters of `Pair` are `TFirst` and `TSecond`: -:::code language="csharp" source="./snippets/shared/Types.cs" id="DefinePairClass"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="DefinePairClass"::: A class type that is declared to take type parameters is called a *generic class type*. Struct, interface, and delegate types can also be generic. When the generic class is used, type arguments must be provided for each of the type parameters: -:::code language="csharp" source="./snippets/shared/Types.cs" id="CreatePairObject"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="CreatePairObject"::: A generic type with type arguments provided, like `Pair` above, is called a *constructed type*. ### Base classes -A class declaration may specify a base class by following the class name and type parameters with a colon and the name of the base class. Omitting a base class specification is the same as deriving from type `object`. In the following example, the base class of `Point3D` is `Point`. From the first example, the base class of `Point` is `object`: +A class declaration may specify a base class. Follow the class name and type parameters with a colon and the name of the base class. Omitting a base class specification is the same as deriving from type `object`. In the following example, the base class of `Point3D` is `Point`. From the first example, the base class of `Point` is `object`: -:::code language="csharp" source="./snippets/shared/Types.cs" id="Create3DPoint"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="Create3DPoint"::: -A class inherits the members of its base class. Inheritance means that a class implicitly contains all members of its base class, except for the instance and static constructors, and the finalizers of the base class. A derived class can add new members to those members it inherits, but it can't remove the definition of an inherited member. In the previous example, `Point3D` inherits the `x` and `y` fields from `Point`, and every `Point3D` instance contains three fields, `x`, `y`, and `z`. +A class inherits the members of its base class. Inheritance means that a class implicitly contains almost all members of its base class. A class doesn't inherit the instance and static constructors, and the finalizer. A derived class can add new members to those members it inherits, but it can't remove the definition of an inherited member. In the previous example, `Point3D` inherits the `x` and `y` fields from `Point`, and every `Point3D` instance contains three fields, `x`, `y`, and `z`. An implicit conversion exists from a class type to any of its base class types. A variable of a class type can reference an instance of that class or an instance of any derived class. For example, given the previous class declarations, a variable of type `Point` can reference either a `Point` or a `Point3D`: -:::code language="csharp" source="./snippets/shared/Types.cs" id="ImplicitCastToBase"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="ImplicitCastToBase"::: ## Structs -Classes define types that support inheritance and polymorphism. They enable you to create sophisticated behaviors based on hierarchies of derived classes. By contrast, ***struct*** types are simpler types whose primary purpose is to store data values. Structs cannot declare a base type; they implicitly derive from . You cannot derive other `struct` types from a `struct` type. They are implicitly sealed. +Classes define types that support inheritance and polymorphism. They enable you to create sophisticated behaviors based on hierarchies of derived classes. By contrast, ***struct*** types are simpler types whose primary purpose is to store data values. Structs can't declare a base type; they implicitly derive from . You can't derive other `struct` types from a `struct` type. They're implicitly sealed. -:::code language="csharp" source="./snippets/shared/Types.cs" id="PointStruct"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="PointStruct"::: ## Interfaces @@ -58,43 +65,43 @@ An ***interface*** defines a contract that can be implemented by classes and str Interfaces may employ ***multiple inheritance***. In the following example, the interface `IComboBox` inherits from both `ITextBox` and `IListBox`. -:::code language="csharp" source="./snippets/shared/Types.cs" id="FirstInterfaces"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="FirstInterfaces"::: Classes and structs can implement multiple interfaces. In the following example, the class `EditBox` implements both `IControl` and `IDataBound`. -:::code language="csharp" source="./snippets/shared/Types.cs" id="ImplementInterfaces"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="ImplementInterfaces"::: When a class or struct implements a particular interface, instances of that class or struct can be implicitly converted to that interface type. For example -:::code language="csharp" source="./snippets/shared/Types.cs" id="UseInterfaces"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="UseInterfaces"::: ## Enums An ***Enum*** type defines a set of constant values. The following `enum` declares constants that define different root vegetables: -:::code language="csharp" source="./snippets/shared/Types.cs" id="EnumDeclaration"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="EnumDeclaration"::: -You can also define an `enum` be used in combination as flags. THe following declaration declares a set of flags for the four seasons. Any combination of the seasons may be applied, including an `All` value that includes all seasons: +You can also define an `enum` be used in combination as flags. The following declaration declares a set of flags for the four seasons. Any combination of the seasons may be applied, including an `All` value that includes all seasons: -:::code language="csharp" source="./snippets/shared/Types.cs" id="FlagsEnumDeclaration"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="FlagsEnumDeclaration"::: The following example shows declarations of both the preceding enums: -:::code language="csharp" source="./snippets/shared/Types.cs" id="UsingEnums"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="UsingEnums"::: ## Nullable types Variables of any type may be declared as ***non-nullable*** or ***nullable***. A nullable variable can hold an additional `null` value, indicating no value. Nullable Value types (structs or enums) are represented by . Non-nullable and Nullable Reference types are both represented by the underlying reference type. The distinction is represented by metadata read by the compiler and some libraries. The compiler provides warnings when nullable references are de-referenced without first checking their value against `null`. The compiler also provides warnings when non-nullable references are assigned to a value that may be `null`. The following example declares a ***nullable int***, initializing it to `null`. Then, it sets the value to `5`. It demonstrates the same concept with a ***nullable string***. -:::code language="csharp" source="./snippets/shared/Types.cs" id="DeclareNullable"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="DeclareNullable"::: ## Tuples -C# supports ***tuples*** which provides concise syntax to group multiple data elements in a lightweight data structure. You instantiate a tuple by declaring the types and names of the members between `(` and `)`, as shown in the following example: +C# supports ***tuples, which provides concise syntax to group multiple data elements in a lightweight data structure. You instantiate a tuple by declaring the types and names of the members between `(` and `)`, as shown in the following example: -:::code language="csharp" source="./snippets/shared/Types.cs" id="DeclareTuples"::: +:::code language="csharp" source="./snippets/shared/Types.cs" ID="DeclareTuples"::: -Tuples provide an alternative when you want a data structure for multiple members, but won't use the building blocks described in the next article. +Tuples provide an alternative for data structure with multiple members, but doesn't use the building blocks described in the next article. >[!div class="step-by-step"] >[Previous](index.md) From 4a9fa0053852aa6df165433f0a86fa0f41dd34cf Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 6 Aug 2020 15:50:41 -0400 Subject: [PATCH 04/11] fix build errors and warnings. --- docs/csharp/tour-of-csharp/features.md | 2 +- docs/csharp/tour-of-csharp/index.md | 2 +- .../tour-of-csharp/program-building-blocks.md | 2 +- .../snippets/shared/Features.cs | 34 ++++++++++++------- docs/csharp/tour-of-csharp/types.md | 4 +-- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/docs/csharp/tour-of-csharp/features.md b/docs/csharp/tour-of-csharp/features.md index d4d7c5d3cf74d..99f936baa39a9 100644 --- a/docs/csharp/tour-of-csharp/features.md +++ b/docs/csharp/tour-of-csharp/features.md @@ -108,7 +108,7 @@ The metadata defined by attributes can be read and manipulated at runtime using The following code sample demonstrates how to get the `HelpAttribute` instances associated to the `Widget` class and its `Display` method. -:::code language="csharp" source="./snippets/shared/attributes/Program.cs" ID="ReadAttributes"::: +:::code language="csharp" source="./snippets/shared/Program.cs" ID="ReadAttributes"::: ## Learn more diff --git a/docs/csharp/tour-of-csharp/index.md b/docs/csharp/tour-of-csharp/index.md index f222543697835..c3517aa174f62 100644 --- a/docs/csharp/tour-of-csharp/index.md +++ b/docs/csharp/tour-of-csharp/index.md @@ -77,7 +77,7 @@ Nullable types don't require a separate definition. For each non-nullable type ` C#'s type system is unified such that a value of any type can be treated as an `object`. Every type in C# directly or indirectly derives from the `object` class type, and `object` is the ultimate base class of all types. Values of reference types are treated as objects simply by viewing the values as type `object`. Values of value types are treated as objects by performing *boxing* and *unboxing operations*. In the following example, an `int` value is converted to `object` and back again to `int`. -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/shared/types-and-variables/Program.cs" ID="boxing" ::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/shared/Program.cs" ID="boxing" ::: When a value of a value type is assigned to an `object` reference, a "box" is allocated to hold the value. That box is an instance of a reference type, and the value is copied into that box. Conversely, when an `object` reference is cast to a value type, a check is made that the referenced `object` is a box of the correct value type. If the check succeeds, the value in the box is copied to the value type. diff --git a/docs/csharp/tour-of-csharp/program-building-blocks.md b/docs/csharp/tour-of-csharp/program-building-blocks.md index aa0dcb0f1cdf6..097882a04e5d4 100644 --- a/docs/csharp/tour-of-csharp/program-building-blocks.md +++ b/docs/csharp/tour-of-csharp/program-building-blocks.md @@ -5,7 +5,7 @@ ms.date: 08/06/2020 --- # Program Building blocks -The types described in the previous article are built using these building blocks: ***members***, ***expressions, and ***statements***. +The types described in the previous article are built using these building blocks: ***members***, ***expressions***, and ***statements***. ## Members diff --git a/docs/csharp/tour-of-csharp/snippets/shared/Features.cs b/docs/csharp/tour-of-csharp/snippets/shared/Features.cs index 3c7cda1db91ee..99da5cd1fc3c1 100644 --- a/docs/csharp/tour-of-csharp/snippets/shared/Features.cs +++ b/docs/csharp/tour-of-csharp/snippets/shared/Features.cs @@ -127,6 +127,14 @@ private static void ReadAttributes() // } + static double[] Apply(double[] a, Function f) + { + double[] result = new double[a.Length]; + for (int i = 0; i < a.Length; i++) result[i] = f(a[i]); + return result; + } + + static void ApplyDelegate() { double[] a = { 0.0, 0.5, 1.0 }; @@ -148,20 +156,22 @@ private static void InitializeArray() int[] a = { 1, 2, 3 }; // } - // - int[] t = new int[3]; - t[0] = 1; - t[1] = 2; - t[2] = 3; - int[] a = t; - // - - // - foreach (int item in a) { - Console.WriteLine(item); + // + int[] t = new int[3]; + t[0] = 1; + t[1] = 2; + t[2] = 3; + int[] a = t; + // + + // + foreach (int item in a) + { + Console.WriteLine(item); + } + // } - // } diff --git a/docs/csharp/tour-of-csharp/types.md b/docs/csharp/tour-of-csharp/types.md index 05e84524143d4..7c5e278feaded 100644 --- a/docs/csharp/tour-of-csharp/types.md +++ b/docs/csharp/tour-of-csharp/types.md @@ -15,8 +15,8 @@ New classes are created using class declarations. A class declaration starts wit - The name of the class - The base class (if given) - The interfaces implemented by the class. -- -- The header is followed by the class body, which consists of a list of member declarations written between the delimiters `{` and `}`. + +The header is followed by the class body, which consists of a list of member declarations written between the delimiters `{` and `}`. The following code shows a declaration of a simple class named `Point`: From f79e61db82c6b033f0336f65dc6adf4914f1398f Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 6 Aug 2020 15:57:47 -0400 Subject: [PATCH 05/11] fix warnings. --- docs/csharp/tour-of-csharp/features.md | 2 +- docs/csharp/tour-of-csharp/snippets/shared/Program.cs | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/csharp/tour-of-csharp/features.md b/docs/csharp/tour-of-csharp/features.md index 99f936baa39a9..e30beb3e638df 100644 --- a/docs/csharp/tour-of-csharp/features.md +++ b/docs/csharp/tour-of-csharp/features.md @@ -108,7 +108,7 @@ The metadata defined by attributes can be read and manipulated at runtime using The following code sample demonstrates how to get the `HelpAttribute` instances associated to the `Widget` class and its `Display` method. -:::code language="csharp" source="./snippets/shared/Program.cs" ID="ReadAttributes"::: +:::code language="csharp" source="./snippets/shared/Features.cs" ID="ReadAttributes"::: ## Learn more diff --git a/docs/csharp/tour-of-csharp/snippets/shared/Program.cs b/docs/csharp/tour-of-csharp/snippets/shared/Program.cs index be291cd9a0607..76131f68a8a93 100644 --- a/docs/csharp/tour-of-csharp/snippets/shared/Program.cs +++ b/docs/csharp/tour-of-csharp/snippets/shared/Program.cs @@ -5,10 +5,19 @@ class Program static void Main(string[] args) { global::Example.Main(); - + Boxing(); Types.Examples(); ClassesObjects.Examples(); Features.Examples(); } + + private static void Boxing() + { + // + int i = 123; + object o = i; // Boxing + int j = (int)o; // Unboxing + // + } } } From 645a0aff904e1d0a3cead12de66a24cbb42a4c00 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 6 Aug 2020 17:19:19 -0400 Subject: [PATCH 06/11] final proofread --- docs/csharp/toc.yml | 2 +- docs/csharp/tour-of-csharp/features.md | 20 ++++++++-------- docs/csharp/tour-of-csharp/index.md | 8 ++++--- .../tour-of-csharp/program-building-blocks.md | 23 ++++++++----------- docs/csharp/tour-of-csharp/types.md | 12 +++++----- 5 files changed, 32 insertions(+), 33 deletions(-) diff --git a/docs/csharp/toc.yml b/docs/csharp/toc.yml index 01f3d9a020c97..efd41b0966a17 100644 --- a/docs/csharp/toc.yml +++ b/docs/csharp/toc.yml @@ -76,7 +76,7 @@ href: tour-of-csharp/types.md - name: Program building blocks href: tour-of-csharp/program-building-blocks.md - - name: Features of C# + - name: Major language areas href: tour-of-csharp/features.md - name: What's new in C# items: diff --git a/docs/csharp/tour-of-csharp/features.md b/docs/csharp/tour-of-csharp/features.md index e30beb3e638df..8bf0712d62a9a 100644 --- a/docs/csharp/tour-of-csharp/features.md +++ b/docs/csharp/tour-of-csharp/features.md @@ -1,17 +1,17 @@ --- -title: A Tour of C# - C# Guide +title: A Tour of C# - Major language areas description: New to C#? Learn the basics of the language. ms.date: 08/06/2020 --- -# Major features +# Major language areas ## Arrays, collections, and LINQ -C# and .NET provide many different collection types. Arrays have syntax defined by the language. General collection types are listed in the namespace. Specialized collections include for accessing continuous memory on the stack frame, and for accessing continuous memory on the managed heap. All collections, including arrays, , and share a unifying principle for iteration. You use the interface. This unifying principle means that any of the collection types can be used with LINQ queries or other algorithms. You write methods using and those algorithms work with any collection. +C# and .NET provide many different collection types. `Arrays` have syntax defined by the language. General collection types are listed in the namespace. Specialized collections include for accessing continuous memory on the stack frame, and for accessing continuous memory on the managed heap. All collections, including arrays, , and share a unifying principle for iteration. You use the interface. This unifying principle means that any of the collection types can be used with LINQ queries or other algorithms. You write methods using and those algorithms work with any collection. ### Arrays -An ***array*** is a data structure that contains a number of variables that are accessed through computed indices. The variables contained in an array, also called the ***elements*** of the array, are all of the same type. This type is called the ***element type*** of the array. +An [***array***](../programming-guide/arrays/index.md) is a data structure that contains a number of variables that are accessed through computed indices. The variables contained in an array, also called the ***elements*** of the array, are all of the same type. This type is called the ***element type*** of the array. Array types are reference types, and the declaration of an array variable simply sets aside space for a reference to an array instance. Actual array instances are created dynamically at runtime using the new operator. The new operation specifies the ***length*** of the new array instance, which is then fixed for the lifetime of the instance. The indices of the elements of an array range from `0` to `Length - 1`. The `new` operator automatically initializes the elements of an array to their default value, which, for example, is zero for all numeric types and `null` for all reference types. @@ -34,7 +34,7 @@ The new operator permits the initial values of the array elements to be specifie :::code language="csharp" source="./snippets/shared/Features.cs" ID="InitializeArray"::: -The length of the array is inferred from the number of expressions between { and }. Local variable and field declarations can be shortened further such that the array type doesn't have to be restated. +The length of the array is inferred from the number of expressions between `{` and `}`. Local variable and field declarations can be shortened further such that the array type doesn't have to be restated. :::code language="csharp" source="./snippets/shared/Features.cs" ID="InitializeShortened"::: @@ -50,7 +50,7 @@ The `foreach` statement uses the class are good examples of parameter array usage. They're declared as follows. +A *parameter array* permits a variable number of arguments to be passed to a method. A parameter array is declared with the `params` modifier. Only the last parameter of a method can be a parameter array, and the type of a parameter array must be a single-dimensional array type. The `Write` and `WriteLine` methods of the class are good examples of parameter array usage. They're declared as follows. :::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="ConsoleExtract"::: @@ -101,9 +101,9 @@ A method can use `return` statements to return control to its caller. In a metho ### Static and instance methods -A method declared with a static modifier is a *static method*. A static method doesn't operate on a specific instance and can only directly access static members. +A method declared with a `static` modifier is a *static method*. A static method doesn't operate on a specific instance and can only directly access static members. -A method declared without a static modifier is an *instance method*. An instance method operates on a specific instance and can access both static and instance members. The instance on which an instance method was invoked can be explicitly accessed as `this`. It's an error to refer to `this` in a static method. +A method declared without a `static` modifier is an *instance method*. An instance method operates on a specific instance and can access both static and instance members. The instance on which an instance method was invoked can be explicitly accessed as `this`. It's an error to refer to `this` in a static method. The following `Entity` class has both static and instance members. @@ -113,7 +113,7 @@ Each `Entity` instance contains a serial number (and presumably some other infor The `GetNextSerialNo` and `SetNextSerialNo` static methods can access the `nextSerialNo` static field, but it would be an error for them to directly access the `serialNo` instance field. -The following example shows the use of the Entity class. +The following example shows the use of the `Entity` class. :::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="UsingEntity"::: @@ -129,7 +129,7 @@ A virtual method can be *overridden* in a derived class. When an instance method An *abstract method* is a virtual method with no implementation. An abstract method is declared with the `abstract` modifier and is permitted only in an abstract class. An abstract method must be overridden in every non-abstract derived class. -The following example declares an abstract class, `Expression`, which represents an expression tree node, and three derived classes, `Constant`, `VariableReference`, and `Operation`, which implement expression tree nodes for constants, variable references, and arithmetic operations. (This example is similar to, but not to be confused with the expression tree types). +The following example declares an abstract class, `Expression`, which represents an expression tree node, and three derived classes, `Constant`, `VariableReference`, and `Operation`, which implement expression tree nodes for constants, variable references, and arithmetic operations. (This example is similar to, but not related to the expression tree types). :::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="WorkingWithExpressions"::: @@ -159,16 +159,13 @@ Members that contain executable code are collectively known as the *function mem The following example shows a generic class called `MyList`, which implements a growable list of objects. The class contains several examples of the most common kinds of function members. -> [!NOTE] -> This example creates a `MyList` class, which is not the same as the .NET standard . It does illustrate the concepts needed for this tour, but is not a replacement for that class. - :::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="ListExample"::: ### Constructors C# supports both instance and static constructors. An *instance constructor* is a member that implements the actions required to initialize an instance of a class. A *static constructor* is a member that implements the actions required to initialize a class itself when it's first loaded. -A constructor is declared like a method with no return type and the same name as the containing class. If a constructor declaration includes a static modifier, it declares a static constructor. Otherwise, it declares an instance constructor. +A constructor is declared like a method with no return type and the same name as the containing class. If a constructor declaration includes a `static` modifier, it declares a static constructor. Otherwise, it declares an instance constructor. Instance constructors can be overloaded and can have optional parameters. For example, the `MyList` class declares one instance constructor with a single optional `int` parameter. Instance constructors are invoked using the `new` operator. The following statements allocate two `MyList` instances using the constructor of the `MyList` class with and without the optional argument. @@ -222,7 +219,7 @@ For advanced scenarios where control of the underlying storage of an event is de An *operator* is a member that defines the meaning of applying a particular expression operator to instances of a class. Three kinds of operators can be defined: unary operators, binary operators, and conversion operators. All operators must be declared as `public` and `static`. -The `MyList` class declares two operators, `operator ==` and `operator !=`. These overridden opeators give new meaning to expressions that apply those operators to `MyList` instances. Specifically, the operators define equality of two `MyList` instances as comparing each of the contained objects using their Equals methods. The following example uses the `==` operator to compare two `MyList` instances. +The `MyList` class declares two operators, `operator ==` and `operator !=`. These overridden opeators give new meaning to expressions that apply those operators to `MyList` instances. Specifically, the operators define equality of two `MyList` instances as comparing each of the contained objects using their `Equals` methods. The following example uses the `==` operator to compare two `MyList` instances. :::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="ListAccess"::: diff --git a/docs/csharp/tour-of-csharp/types.md b/docs/csharp/tour-of-csharp/types.md index 7c5e278feaded..01070a843ff1c 100644 --- a/docs/csharp/tour-of-csharp/types.md +++ b/docs/csharp/tour-of-csharp/types.md @@ -30,7 +30,7 @@ The memory occupied by an object is automatically reclaimed when the object is n ### Type parameters -Generic classes define ***type parameters***. Type parameters are a list of type parameters names enclosed in angle brackets. Type parameters follow the class name. The type parameters can then be used in the body of the class declarations to define the members of the class. In the following example, the type parameters of `Pair` are `TFirst` and `TSecond`: +Generic classes define [***type parameters***](programming-guide/generics/index.md). Type parameters are a list of type parameters names enclosed in angle brackets. Type parameters follow the class name. The type parameters can then be used in the body of the class declarations to define the members of the class. In the following example, the type parameters of `Pair` are `TFirst` and `TSecond`: :::code language="csharp" source="./snippets/shared/Types.cs" ID="DefinePairClass"::: @@ -55,13 +55,13 @@ An implicit conversion exists from a class type to any of its base class types. ## Structs -Classes define types that support inheritance and polymorphism. They enable you to create sophisticated behaviors based on hierarchies of derived classes. By contrast, ***struct*** types are simpler types whose primary purpose is to store data values. Structs can't declare a base type; they implicitly derive from . You can't derive other `struct` types from a `struct` type. They're implicitly sealed. +Classes define types that support inheritance and polymorphism. They enable you to create sophisticated behaviors based on hierarchies of derived classes. By contrast, [***struct***](../language-reference/builtin-types/value-types.md) types are simpler types whose primary purpose is to store data values. Structs can't declare a base type; they implicitly derive from . You can't derive other `struct` types from a `struct` type. They're implicitly sealed. :::code language="csharp" source="./snippets/shared/Types.cs" ID="PointStruct"::: ## Interfaces -An ***interface*** defines a contract that can be implemented by classes and structs. An interface can contain methods, properties, events, and indexers. An interface typically doesn't provide implementations of the members it defines—it merely specifies the members that must be supplied by classes or structs that implement the interface. +An [***interface***](programming-guide/interfaces/index.md) defines a contract that can be implemented by classes and structs. An interface can contain methods, properties, events, and indexers. An interface typically doesn't provide implementations of the members it defines—it merely specifies the members that must be supplied by classes or structs that implement the interface. Interfaces may employ ***multiple inheritance***. In the following example, the interface `IComboBox` inherits from both `ITextBox` and `IListBox`. @@ -77,7 +77,7 @@ When a class or struct implements a particular interface, instances of that clas ## Enums -An ***Enum*** type defines a set of constant values. The following `enum` declares constants that define different root vegetables: +An [***Enum***](../language-reference/builtin-types/enum.md) type defines a set of constant values. The following `enum` declares constants that define different root vegetables: :::code language="csharp" source="./snippets/shared/Types.cs" ID="EnumDeclaration"::: @@ -91,13 +91,13 @@ The following example shows declarations of both the preceding enums: ## Nullable types -Variables of any type may be declared as ***non-nullable*** or ***nullable***. A nullable variable can hold an additional `null` value, indicating no value. Nullable Value types (structs or enums) are represented by . Non-nullable and Nullable Reference types are both represented by the underlying reference type. The distinction is represented by metadata read by the compiler and some libraries. The compiler provides warnings when nullable references are de-referenced without first checking their value against `null`. The compiler also provides warnings when non-nullable references are assigned to a value that may be `null`. The following example declares a ***nullable int***, initializing it to `null`. Then, it sets the value to `5`. It demonstrates the same concept with a ***nullable string***. +Variables of any type may be declared as ***non-nullable*** or ***nullable***. A nullable variable can hold an additional `null` value, indicating no value. Nullable Value types (structs or enums) are represented by . Non-nullable and Nullable Reference types are both represented by the underlying reference type. The distinction is represented by metadata read by the compiler and some libraries. The compiler provides warnings when nullable references are de-referenced without first checking their value against `null`. The compiler also provides warnings when non-nullable references are assigned to a value that may be `null`. The following example declares a ***nullable int***, initializing it to `null`. Then, it sets the value to `5`. It demonstrates the same concept with a ***nullable string***. For more information, see [nullable value types](language-reference/builtin-types/nullable-value-types.md) and [nullable reference types](../nullable-references.md). :::code language="csharp" source="./snippets/shared/Types.cs" ID="DeclareNullable"::: ## Tuples -C# supports ***tuples, which provides concise syntax to group multiple data elements in a lightweight data structure. You instantiate a tuple by declaring the types and names of the members between `(` and `)`, as shown in the following example: +C# supports [***tuples***](../language-reference/builtin-types/value-tuples.md), which provides concise syntax to group multiple data elements in a lightweight data structure. You instantiate a tuple by declaring the types and names of the members between `(` and `)`, as shown in the following example: :::code language="csharp" source="./snippets/shared/Types.cs" ID="DeclareTuples"::: From 8e03856925b8bba48df196780acbb5317440220b Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Fri, 7 Aug 2020 12:03:22 -0400 Subject: [PATCH 07/11] Apply suggestions from code review Co-authored-by: Petr Kulikov --- docs/csharp/tour-of-csharp/features.md | 6 +++--- docs/csharp/tour-of-csharp/types.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/csharp/tour-of-csharp/features.md b/docs/csharp/tour-of-csharp/features.md index 8bf0712d62a9a..5fed08cccc81f 100644 --- a/docs/csharp/tour-of-csharp/features.md +++ b/docs/csharp/tour-of-csharp/features.md @@ -48,7 +48,7 @@ The `foreach` statement can be used to enumerate the elements of any collection. The `foreach` statement uses the interface, so can work with any collection. -## string interpolation +## String interpolation C# [***string interpolation***](../language-reference/tokens/interpolated.md) enables you to format strings by define expressions whose results are placed in a format string. For example, the following example prints the temperature on a given day from a set of weather data: @@ -56,7 +56,7 @@ C# [***string interpolation***](../language-reference/tokens/interpolated.md) en An interpolated string is declared using the `$` token. String interpolation evaluates the expressions between `{` and `}`, then converts the result to a `string`, and replaces the text between the brackets with the string result of the expression. The `:` in the first expression, `{weatherData.Data:MM-DD-YYYY}` specifies the *format string*. In the preceding example, it specifies that the date should be printed in "MM-DD-YYYY" format. -## Pattern Matching +## Pattern matching The C# language provides [***pattern matching***](../pattern-matching.md) expressions to query the state of an object and execute code based on that state. You can inspect types and the values of properties and fields to determine which action to take. The `switch` expression is the primary expression for pattern matching. @@ -80,7 +80,7 @@ A delegate doesn't know or care about the class of the method it references. All ## async / await -C# supports asynchronous programs with two keywords: `async` and `await`. You add the `async` modifier to a method declaration to declare the method is asynchronous. The `aawit` operator tells the compiler that to asynchronously await for a result to finish. Control is returned to the caller, and the method returns a structure that manages the state of the asynchronous work. The structure is typically a , but can be any type that supports the awaiter pattern. These features enable you to write code that reads as its synchronous counterpart, but executes asynchronously. For example, the following code downloads the home page for [Microsoft docs](https://docs.microsoft.com): +C# supports asynchronous programs with two keywords: `async` and `await`. You add the `async` modifier to a method declaration to declare the method is asynchronous. The `await` operator tells the compiler that to asynchronously await for a result to finish. Control is returned to the caller, and the method returns a structure that manages the state of the asynchronous work. The structure is typically a , but can be any type that supports the awaiter pattern. These features enable you to write code that reads as its synchronous counterpart, but executes asynchronously. For example, the following code downloads the home page for [Microsoft docs](https://docs.microsoft.com): :::code language="csharp" source="./snippets/shared/Features.cs" ID="AsyncExample"::: diff --git a/docs/csharp/tour-of-csharp/types.md b/docs/csharp/tour-of-csharp/types.md index 01070a843ff1c..c1e03f4aabe9f 100644 --- a/docs/csharp/tour-of-csharp/types.md +++ b/docs/csharp/tour-of-csharp/types.md @@ -55,7 +55,7 @@ An implicit conversion exists from a class type to any of its base class types. ## Structs -Classes define types that support inheritance and polymorphism. They enable you to create sophisticated behaviors based on hierarchies of derived classes. By contrast, [***struct***](../language-reference/builtin-types/value-types.md) types are simpler types whose primary purpose is to store data values. Structs can't declare a base type; they implicitly derive from . You can't derive other `struct` types from a `struct` type. They're implicitly sealed. +Classes define types that support inheritance and polymorphism. They enable you to create sophisticated behaviors based on hierarchies of derived classes. By contrast, [***struct***](../language-reference/builtin-types/struct.md) types are simpler types whose primary purpose is to store data values. Structs can't declare a base type; they implicitly derive from . You can't derive other `struct` types from a `struct` type. They're implicitly sealed. :::code language="csharp" source="./snippets/shared/Types.cs" ID="PointStruct"::: From 9a01a7c302ce7889df4d77ec75e46f7f0f648330 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Fri, 7 Aug 2020 12:05:25 -0400 Subject: [PATCH 08/11] build error & incorect code fence. --- docs/csharp/tour-of-csharp/features.md | 2 +- docs/csharp/tour-of-csharp/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/csharp/tour-of-csharp/features.md b/docs/csharp/tour-of-csharp/features.md index 8bf0712d62a9a..4217a74069a5d 100644 --- a/docs/csharp/tour-of-csharp/features.md +++ b/docs/csharp/tour-of-csharp/features.md @@ -7,7 +7,7 @@ ms.date: 08/06/2020 ## Arrays, collections, and LINQ -C# and .NET provide many different collection types. `Arrays` have syntax defined by the language. General collection types are listed in the namespace. Specialized collections include for accessing continuous memory on the stack frame, and for accessing continuous memory on the managed heap. All collections, including arrays, , and share a unifying principle for iteration. You use the interface. This unifying principle means that any of the collection types can be used with LINQ queries or other algorithms. You write methods using and those algorithms work with any collection. +C# and .NET provide many different collection types. Arrays have syntax defined by the language. General collection types are listed in the namespace. Specialized collections include for accessing continuous memory on the stack frame, and for accessing continuous memory on the managed heap. All collections, including arrays, , and share a unifying principle for iteration. You use the interface. This unifying principle means that any of the collection types can be used with LINQ queries or other algorithms. You write methods using and those algorithms work with any collection. ### Arrays diff --git a/docs/csharp/tour-of-csharp/index.md b/docs/csharp/tour-of-csharp/index.md index 9a2c67a40b628..0859aaac9fb86 100644 --- a/docs/csharp/tour-of-csharp/index.md +++ b/docs/csharp/tour-of-csharp/index.md @@ -10,7 +10,7 @@ C# (pronounced "See Sharp") is a modern, object-oriented, and type-safe programm C# is an object-oriented, ***component-oriented*** programming. C# provides language constructs to support directly these concepts, making C# a natural language in which to create and use software components. Since its origin, C# has added features to support new workloads and emerging software design practices. -Several C# features aid in the construction of robust and durable applications. [***Garbage collection***](../../standard/garbage-collection/index.md) automatically reclaims memory occupied by unreachable unused objects. [***Exception handling***](../programming-guide/exceptions/index.md) provides a structured and extensible approach to error detection and recovery. [***Lambda expressions***](../programming-guide/statements-expressions-operators/lambda-expressions.md) support functional programming techniques. [***Query syntax***](../linq/index.md) creates a common pattern for working with data from any source. Language support for [***asynchronous operations***](../programming-guide/concepts/async/index.md) provides syntax for building distributed systems.[ ***Pattern matching***](..//pattern-matching.md) provides syntax to easily separate data from algorithms in modern distributed systems. C# has a [***unified type system***](../programming-guide/types/index.md). All C# types, including primitive types such as `int` and `double`, inherit from a single root `object` type. All types share a set of common operations. Values of any type can be stored, transported, and operated upon in a consistent manner. Furthermore, C# supports both user-defined reference types and value types. C# allows dynamic allocation of objects and in-line storage of lightweight structures. +Several C# features aid in the construction of robust and durable applications. [***Garbage collection***](../../standard/garbage-collection/index.md) automatically reclaims memory occupied by unreachable unused objects. [***Exception handling***](../programming-guide/exceptions/index.md) provides a structured and extensible approach to error detection and recovery. [***Lambda expressions***](../programming-guide/statements-expressions-operators/lambda-expressions.md) support functional programming techniques. [***Query syntax***](../linq/index.md) creates a common pattern for working with data from any source. Language support for [***asynchronous operations***](../programming-guide/concepts/async/index.md) provides syntax for building distributed systems. [***Pattern matching***](..//pattern-matching.md) provides syntax to easily separate data from algorithms in modern distributed systems. C# has a [***unified type system***](../programming-guide/types/index.md). All C# types, including primitive types such as `int` and `double`, inherit from a single root `object` type. All types share a set of common operations. Values of any type can be stored, transported, and operated upon in a consistent manner. Furthermore, C# supports both user-defined reference types and value types. C# allows dynamic allocation of objects and in-line storage of lightweight structures. C# emphasizes ***versioning*** to ensure programs and libraries can evolve over time in a compatible manner. Aspects of C#'s design that were directly influenced by versioning considerations include the separate `virtual` and `override` modifiers, the rules for method overload resolution, and support for explicit interface member declarations. From cc2cf501b83bc3cd87012943f5c4313270cd4841 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Fri, 7 Aug 2020 14:06:41 -0400 Subject: [PATCH 09/11] fix any redirections --- .openpublishing.redirection.json | 32 +++++++++++++++++++ .../snippets/shared/Features.cs | 4 +-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index 80452aadc40a8..7360507cfa50a 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -1760,14 +1760,46 @@ "source_path": "docs/csharp/structs.md", "redirect_url": "/dotnet/csharp/language-reference/builtin-types/struct" }, + { + "source_path": "docs/csharp/tour-of-csharp/arrays.md", + "redirect_url": "/dotnet/csharp/tour-of-csharp/features#arrays-collections-and-LINQ" + }, + { + "source_path": "docs/csharp/tour-of-csharp/attributes.md", + "redirect_url": "/dotnet/csharp/tour-of-csharp/features#attributes" + }, + { + "source_path": "docs/csharp/tour-of-csharp/delegates.md", + "redirect_url": "/dotnet/csharp/tour-of-csharp/features#delegates-and-lambda-expressions" + }, { "source_path": "docs/csharp/tour-of-csharp/enums.md", "redirect_url": "/dotnet/csharp/language-reference/builtin-types/enum" }, + { + "source_path": "docs/csharp/tour-of-csharp/expressions.md", + "redirect_url": "/dotnet/csharp/tour-of-csharp/program-building-blocks#expressions" + }, + { + "source_path": "docs/csharp/tour-of-csharp/interfaces.md", + "redirect_url": "/dotnet/csharp/tour-of-csharp/types#interfaces" + }, + { + "source_path": "docs/csharp/tour-of-csharp/program-structure.md", + "redirect_url": "/dotnet/csharp/tour-of-csharp/#program-structure" + }, + { + "source_path": "docs/csharp/tour-of-csharp/statements.md", + "redirect_url": "/dotnet/csharp/tour-of-csharp/program-building-blocks#statements" + }, { "source_path": "docs/csharp/tour-of-csharp/structs.md", "redirect_url": "/dotnet/csharp/language-reference/builtin-types/struct" }, + { + "source_path": "docs/csharp/tour-of-csharp/types-and-variables.md", + "redirect_url": "/dotnet/csharp/tour-of-csharp/types" + }, { "source_path": "docs/csharp/tuples.md", "redirect_url": "/dotnet/csharp/language-reference/builtin-types/value-tuples" diff --git a/docs/csharp/tour-of-csharp/snippets/shared/Features.cs b/docs/csharp/tour-of-csharp/snippets/shared/Features.cs index 99da5cd1fc3c1..ec40572c523e6 100644 --- a/docs/csharp/tour-of-csharp/snippets/shared/Features.cs +++ b/docs/csharp/tour-of-csharp/snippets/shared/Features.cs @@ -59,10 +59,10 @@ public string Topic // // - [Help("https://docs.microsoft.com/dotnet/csharp/tour-of-csharp/attributes")] + [Help("https://docs.microsoft.com/dotnet/csharp/tour-of-csharp/features")] public class Widget { - [Help("https://docs.microsoft.com/dotnet/csharp/tour-of-csharp/attributes", + [Help("https://docs.microsoft.com/dotnet/csharp/tour-of-csharp/features", Topic = "Display")] public void Display(string text) { } } From 91afab378ef605fbdd502ef66b362044ff15cf0f Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Mon, 10 Aug 2020 10:57:24 -0400 Subject: [PATCH 10/11] Apply suggestions from code review Co-authored-by: Tom Dykstra Co-authored-by: David Pine --- docs/csharp/tour-of-csharp/features.md | 10 +- docs/csharp/tour-of-csharp/index.md | 10 +- .../tour-of-csharp/program-building-blocks.md | 8 +- .../snippets/shared/AcmeStack.cs | 24 +-- .../snippets/shared/ClassesObjects.cs | 166 ++++++++---------- .../snippets/shared/Features.cs | 37 ++-- .../snippets/shared/StackUsage.cs | 5 +- .../tour-of-csharp/snippets/shared/Types.cs | 44 ++--- docs/csharp/tour-of-csharp/types.md | 12 +- 9 files changed, 155 insertions(+), 161 deletions(-) diff --git a/docs/csharp/tour-of-csharp/features.md b/docs/csharp/tour-of-csharp/features.md index 6b2cfa3059cd5..fd4ad5786f334 100644 --- a/docs/csharp/tour-of-csharp/features.md +++ b/docs/csharp/tour-of-csharp/features.md @@ -13,7 +13,7 @@ C# and .NET provide many different collection types. Arrays have syntax defined An [***array***](../programming-guide/arrays/index.md) is a data structure that contains a number of variables that are accessed through computed indices. The variables contained in an array, also called the ***elements*** of the array, are all of the same type. This type is called the ***element type*** of the array. -Array types are reference types, and the declaration of an array variable simply sets aside space for a reference to an array instance. Actual array instances are created dynamically at runtime using the new operator. The new operation specifies the ***length*** of the new array instance, which is then fixed for the lifetime of the instance. The indices of the elements of an array range from `0` to `Length - 1`. The `new` operator automatically initializes the elements of an array to their default value, which, for example, is zero for all numeric types and `null` for all reference types. +Array types are reference types, and the declaration of an array variable simply sets aside space for a reference to an array instance. Actual array instances are created dynamically at runtime using the `new` operator. The `new` operation specifies the ***length*** of the new array instance, which is then fixed for the lifetime of the instance. The indices of the elements of an array range from `0` to `Length - 1`. The `new` operator automatically initializes the elements of an array to their default value, which, for example, is zero for all numeric types and `null` for all reference types. The following example creates an array of `int` elements, initializes the array, and prints out the contents of the array. @@ -30,7 +30,7 @@ The element type of an array can be any type, including an array type. An array The first line creates an array with three elements, each of type `int[]` and each with an initial value of `null`. The next lines then initialize the three elements with references to individual array instances of varying lengths. -The new operator permits the initial values of the array elements to be specified using an ***array initializer***, which is a list of expressions written between the delimiters `{` and `}`. The following example allocates and initializes an `int[]` with three elements. +The `new` operator permits the initial values of the array elements to be specified using an ***array initializer***, which is a list of expressions written between the delimiters `{` and `}`. The following example allocates and initializes an `int[]` with three elements. :::code language="csharp" source="./snippets/shared/Features.cs" ID="InitializeArray"::: @@ -50,7 +50,7 @@ The `foreach` statement uses the , but can be any type that supports the awaiter pattern. These features enable you to write code that reads as its synchronous counterpart, but executes asynchronously. For example, the following code downloads the home page for [Microsoft docs](https://docs.microsoft.com): +C# supports asynchronous programs with two keywords: `async` and `await`. You add the `async` modifier to a method declaration to declare the method is asynchronous. The `await` operator tells the compiler to asynchronously await for a result to finish. Control is returned to the caller, and the method returns a structure that manages the state of the asynchronous work. The structure is typically a , but can be any type that supports the awaiter pattern. These features enable you to write code that reads as its synchronous counterpart, but executes asynchronously. For example, the following code downloads the home page for [Microsoft docs](https://docs.microsoft.com): :::code language="csharp" source="./snippets/shared/Features.cs" ID="AsyncExample"::: @@ -88,7 +88,7 @@ This small sample shows the major features for asynchronous programming: - The method declaration includes the `async` modifier. - The body of the method `await`s the return of the `GetByteArrayAsync` method. -- The type specified in the `return` statement matches the type argument in the `TaskL` declaration for the method. (A method that returns a `Task` would use `return` statements without any argument). +- The type specified in the `return` statement matches the type argument in the `Task` declaration for the method. (A method that returns a `Task` would use `return` statements without any argument). ## Attributes diff --git a/docs/csharp/tour-of-csharp/index.md b/docs/csharp/tour-of-csharp/index.md index 0859aaac9fb86..8d5acf7d610bd 100644 --- a/docs/csharp/tour-of-csharp/index.md +++ b/docs/csharp/tour-of-csharp/index.md @@ -8,7 +8,7 @@ ms.date: 08/06/2020 C# (pronounced "See Sharp") is a modern, object-oriented, and type-safe programming language. C# has its roots in the C family of languages and will be immediately familiar to C, C++, Java, and JavaScript programmers. This tour provides an overview of the major components of the language in C# 8 and earlier. If you want to explore the language through interactive examples, try the [introduction to C#](../tutorials/intro-to-csharp/index.md) tutorials. -C# is an object-oriented, ***component-oriented*** programming. C# provides language constructs to support directly these concepts, making C# a natural language in which to create and use software components. Since its origin, C# has added features to support new workloads and emerging software design practices. +C# is an object-oriented, ***component-oriented*** programming language. C# provides language constructs to directly support these concepts, making C# a natural language in which to create and use software components. Since its origin, C# has added features to support new workloads and emerging software design practices. Several C# features aid in the construction of robust and durable applications. [***Garbage collection***](../../standard/garbage-collection/index.md) automatically reclaims memory occupied by unreachable unused objects. [***Exception handling***](../programming-guide/exceptions/index.md) provides a structured and extensible approach to error detection and recovery. [***Lambda expressions***](../programming-guide/statements-expressions-operators/lambda-expressions.md) support functional programming techniques. [***Query syntax***](../linq/index.md) creates a common pattern for working with data from any source. Language support for [***asynchronous operations***](../programming-guide/concepts/async/index.md) provides syntax for building distributed systems. [***Pattern matching***](..//pattern-matching.md) provides syntax to easily separate data from algorithms in modern distributed systems. C# has a [***unified type system***](../programming-guide/types/index.md). All C# types, including primitive types such as `int` and `double`, inherit from a single root `object` type. All types share a set of common operations. Values of any type can be stored, transported, and operated upon in a consistent manner. Furthermore, C# supports both user-defined reference types and value types. C# allows dynamic allocation of objects and in-line storage of lightweight structures. @@ -40,7 +40,7 @@ The following outline provides an overview of C#'s type system. - [Simple types](../language-reference/builtin-types/value-types.md#built-in-value-types) - [Signed integral](../language-reference/builtin-types/integral-numeric-types.md): `sbyte`, `short`, `int`, `long` - [Unsigned integral](../language-reference/builtin-types/integral-numeric-types.md): `byte`, `ushort`, `uint`, `ulong` - - Unicode characters: `char`, which represents a UTF-16 code unit + - [Unicode characters](/dotnet/standard/base-types/character-encoding-introduction): `char`, which represents a UTF-16 code unit - [IEEE binary floating-point](../language-reference/builtin-types/floating-point-numeric-types.md): `float`, `double` - [High-precision decimal floating-point](../language-reference/builtin-types/floating-point-numeric-types.md): `decimal` - Boolean: `bool`, which represents Boolean values—values that are either `true` or `false` @@ -55,12 +55,12 @@ The following outline provides an overview of C#'s type system. - [Reference types](../language-reference/keywords/reference-types.md) - [Class types](../language-reference/keywords/class.md) - Ultimate base class of all other types: `object` - - Unicode strings: `string`, which represents a sequence of UTF-16 code units + - [Unicode strings](/dotnet/standard/base-types/character-encoding-introduction): `string`, which represents a sequence of UTF-16 code units - User-defined types of the form `class C {...}` - [Interface types](../language-reference/keywords/interface.md) - User-defined types of the form `interface I {...}` - [Array types](../programming-guide/arrays/index.md) - - Single- and multi-dimensional, for example, `int[]` and `int[,]` + - Single- and multi-dimensional and jagged, for example, `int[]`, `int[,]`, and `int[][]` - [Delegate types](../language-reference/keywords/delegate.md) - User-defined types of the form `delegate int D(...)` @@ -73,7 +73,7 @@ C# programs use *type declarations* to create new types. A type declaration spec The `class`, `struct`, `interface`, and `delegate` types all support generics, whereby they can be parameterized with other types. -C# supports single- and multi-dimensional arrays of any type. Unlike the types listed above, array types don't have to be declared before they can be used. Instead, array types are constructed by following a type name with square brackets. For example, `int[]` is a single-dimensional array of `int`, `int[,]` is a two-dimensional array of `int`, and `int[][]` is a single-dimensional array of single-dimensional array of `int`. +C# supports single- and multi-dimensional arrays of any type. Unlike the types listed above, array types don't have to be declared before they can be used. Instead, array types are constructed by following a type name with square brackets. For example, `int[]` is a single-dimensional array of `int`, `int[,]` is a two-dimensional array of `int`, and `int[][]` is a single-dimensional array of single-dimensional array or "jagged" array of `int`. Nullable types don't require a separate definition. For each non-nullable type `T`, there's a corresponding nullable type `T?`, which can hold an additional value, `null`. For instance, `int?` is a type that can hold any 32-bit integer or the value `null`, and `string?` is a type that can hold any `string` or the value `null`. diff --git a/docs/csharp/tour-of-csharp/program-building-blocks.md b/docs/csharp/tour-of-csharp/program-building-blocks.md index 5f2af86de6ef7..1c6cf1070b077 100644 --- a/docs/csharp/tour-of-csharp/program-building-blocks.md +++ b/docs/csharp/tour-of-csharp/program-building-blocks.md @@ -1,9 +1,9 @@ --- -title: "The building blocks of C# programs: Learn about members, expressions, and statements." -description: Types contain members you write. Those members are built from statements and expressions. +title: The building blocks of C# programs" +description: Learn about C# members, expressions, and statements. Types contain members you write. Those members are built from statements and expressions. ms.date: 08/06/2020 --- -# Program Building blocks +# Program building blocks The types described in the previous article are built using these building blocks: [***members***](../programming-guide/classes-and-structs/members.md), [***expressions***, and ***statements***](../programming-guide/statements-expressions-operators/index.md). @@ -219,7 +219,7 @@ For advanced scenarios where control of the underlying storage of an event is de An *operator* is a member that defines the meaning of applying a particular expression operator to instances of a class. Three kinds of operators can be defined: unary operators, binary operators, and conversion operators. All operators must be declared as `public` and `static`. -The `MyList` class declares two operators, `operator ==` and `operator !=`. These overridden opeators give new meaning to expressions that apply those operators to `MyList` instances. Specifically, the operators define equality of two `MyList` instances as comparing each of the contained objects using their `Equals` methods. The following example uses the `==` operator to compare two `MyList` instances. +The `MyList` class declares two operators, `operator ==` and `operator !=`. These overridden operators give new meaning to expressions that apply those operators to `MyList` instances. Specifically, the operators define equality of two `MyList` instances as comparing each of the contained objects using their `Equals` methods. The following example uses the `==` operator to compare two `MyList` instances. :::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="ListAccess"::: diff --git a/docs/csharp/tour-of-csharp/snippets/shared/AcmeStack.cs b/docs/csharp/tour-of-csharp/snippets/shared/AcmeStack.cs index 1c045830d105e..bcf4da19e2f56 100644 --- a/docs/csharp/tour-of-csharp/snippets/shared/AcmeStack.cs +++ b/docs/csharp/tour-of-csharp/snippets/shared/AcmeStack.cs @@ -1,33 +1,37 @@ -using System; +using System; + namespace Acme.Collections { public class Stack { - Entry top; + Entry _top; + public void Push(T data) { - top = new Entry(top, data); + _top = new Entry(top, data); } public T Pop() { - if (top == null) + if (_top == null) { throw new InvalidOperationException(); } - T result = top.data; - top = top.next; + T result = _top.Data; + _top = _top.Next; + return result; } class Entry { - public Entry next; - public T data; + public Entry Next { get; set; } + public T Data { get; set; } + public Entry(Entry next, T data) { - this.next = next; - this.data = data; + Next = next; + Data = data; } } } diff --git a/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs b/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs index 9d8fd40cebee2..debc3924e4600 100644 --- a/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs +++ b/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs @@ -23,12 +23,16 @@ public class Color public static readonly Color Red = new Color(255, 0, 0); public static readonly Color Green = new Color(0, 255, 0); public static readonly Color Blue = new Color(0, 0, 255); - private byte r, g, b; + + public byte R { get; } + public byte G { get; } + public byte B { get; } + public Color(byte r, byte g, byte b) { - this.r = r; - this.g = g; - this.b = b; + R = r; + G = g; + B = b; } } // @@ -53,23 +57,27 @@ public static void WriteSquares() // class Entity { - static int nextSerialNo; - int serialNo; + static int s_nextSerialNo; + int _serialNo; + public Entity() { - serialNo = nextSerialNo++; + _serialNo = s_nextSerialNo++; } + public int GetSerialNo() { - return serialNo; + return _serialNo; } + public static int GetNextSerialNo() { - return nextSerialNo; + return s_nextSerialNo; } + public static void SetNextSerialNo(int value) { - nextSerialNo = value; + s_nextSerialNo = value; } } // @@ -79,58 +87,64 @@ public abstract class Expression { public abstract double Evaluate(Dictionary vars); } + public class Constant : Expression { - double value; + double _value; + public Constant(double value) { - this.value = value; + _value = value; } + public override double Evaluate(Dictionary vars) { - return value; + return _value; } } + public class VariableReference : Expression { - string name; + string _name; + public VariableReference(string name) { - this.name = name; + _name = name; } + public override double Evaluate(Dictionary vars) { - object value = vars[name]; - if (value == null) - { - throw new Exception("Unknown variable: " + name); - } + object value = vars[name] ?? throw new Exception($"Unknown variable: {name}"); return Convert.ToDouble(value); } } + public class Operation : Expression { - Expression left; - char op; - Expression right; + Expression _left; + char _op; + Expression _right; + public Operation(Expression left, char op, Expression right) { - this.left = left; - this.op = op; - this.right = right; + _left = left; + _op = op; + _right = right; } + public override double Evaluate(Dictionary vars) { - double x = left.Evaluate(vars); - double y = right.Evaluate(vars); + double x = _left.Evaluate(vars); + double y = _right.Evaluate(vars); switch (op) { case '+': return x + y; case '-': return x - y; case '*': return x * y; case '/': return x / y; + + default: throw new Exception("Unknown operator"); } - throw new Exception("Unknown operator"); } } // @@ -138,30 +152,13 @@ public override double Evaluate(Dictionary vars) // class OverloadingExample { - static void F() - { - Console.WriteLine("F()"); - } - static void F(object x) - { - Console.WriteLine("F(object)"); - } - static void F(int x) - { - Console.WriteLine("F(int)"); - } - static void F(double x) - { - Console.WriteLine("F(double)"); - } - static void F(T x) - { - Console.WriteLine("F(T)"); - } - static void F(double x, double y) - { - Console.WriteLine("F(double, double)"); - } + static void F() => Console.WriteLine("F()"); + static void F(object x) => Console.WriteLine("F(object)"); + static void F(int x) => Console.WriteLine("F(int)"); + static void F(double x) => Console.WriteLine("F(double)"); + static void F(T x) => Console.WriteLine("F(T)"); + static void F(double x, double y) => Console.WriteLine("F(double, double)"); + public static void UsageExample() { F(); // Invokes F() @@ -179,57 +176,48 @@ public static void UsageExample() // public class MyList { - // Constant - const int defaultCapacity = 4; + const int DefaultCapacity = 4; - // Fields - T[] items; - int count; + T[] _items; + int _count; - // Constructor - public MyList(int capacity = defaultCapacity) + public MyList(int capacity = DefaultCapacity) { - items = new T[capacity]; + _items = new T[capacity]; } - // Properties - public int Count => count; + public int Count => _count; public int Capacity { - get { return items.Length; } + get => _items.Length; set { - if (value < count) value = count; - if (value != items.Length) + if (value < _count) value = _count; + if (value != _items.Length) { T[] newItems = new T[value]; - Array.Copy(items, 0, newItems, 0, count); - items = newItems; + Array.Copy(_items, 0, newItems, 0, count); + _items = newItems; } } } - // Indexer public T this[int index] { - get - { - return items[index]; - } + get => _items[index]; set { - items[index] = value; + _items[index] = value; OnChanged(); } } - // Methods public void Add(T item) { - if (count == Capacity) Capacity = count * 2; - items[count] = item; - count++; + if (_count == Capacity) Capacity = _count * 2; + items[_count] = item; + _count++; OnChanged(); } protected virtual void OnChanged() => @@ -253,10 +241,8 @@ static bool Equals(MyList a, MyList b) return true; } - // Event public event EventHandler Changed; - // Operators public static bool operator ==(MyList a, MyList b) => Equals(a, b); @@ -268,19 +254,21 @@ static bool Equals(MyList a, MyList b) // class EventExample { - static int changeCount; + static int s_changeCount; + static void ListChanged(object sender, EventArgs e) { - changeCount++; + s_changeCount++; } + public static void Usage() { - MyList names = new MyList(); + var names = new MyList(); names.Changed += new EventHandler(ListChanged); names.Add("Liz"); names.Add("Martha"); names.Add("Beth"); - Console.WriteLine(changeCount); // Outputs "3" + Console.WriteLine(changeCount); // "3" } } // @@ -295,11 +283,12 @@ static void Swap(ref int x, ref int y) x = y; y = temp; } + public static void SwapExample() { int i = 1, j = 2; Swap(ref i, ref j); - Console.WriteLine($"{i} {j}"); // Outputs "2 1" + Console.WriteLine($"{i} {j}"); // "2 1" } // @@ -309,10 +298,11 @@ static void Divide(int x, int y, out int result, out int remainder) result = x / y; remainder = x % y; } + public static void OutUsage() { Divide(10, 3, out int res, out int rem); - Console.WriteLine($"{res} {rem}"); // Outputs "3 1" + Console.WriteLine($"{res} {rem}"); // "3 1" } // @@ -379,10 +369,10 @@ private static void UsingExpressions() Dictionary vars = new Dictionary(); vars["x"] = 3; vars["y"] = 5; - Console.WriteLine(e.Evaluate(vars)); // Outputs "21" + Console.WriteLine(e.Evaluate(vars)); // "21" vars["x"] = 1.5; vars["y"] = 9; - Console.WriteLine(e.Evaluate(vars)); // Outputs "16.5" + Console.WriteLine(e.Evaluate(vars)); // "16.5" // } diff --git a/docs/csharp/tour-of-csharp/snippets/shared/Features.cs b/docs/csharp/tour-of-csharp/snippets/shared/Features.cs index ec40572c523e6..3e7e665ff2d45 100644 --- a/docs/csharp/tour-of-csharp/snippets/shared/Features.cs +++ b/docs/csharp/tour-of-csharp/snippets/shared/Features.cs @@ -7,26 +7,25 @@ namespace TourOfCsharp // delegate double Function(double x); + class Multiplier { - double factor; - public Multiplier(double factor) - { - this.factor = factor; - } - public double Multiply(double x) - { - return x * factor; - } + double _factor; + + public Multiplier(double factor) => _factor = factor; + + public double Multiply(double x) => x * _factor; } + class DelegateExample { static double[] Apply(double[] a, Function f) { - double[] result = new double[a.Length]; + var result = new double[a.Length]; for (int i = 0; i < a.Length; i++) result[i] = f(a[i]); return result; } + public static void Main() { double[] a = { 0.0, 0.5, 1.0 }; @@ -41,19 +40,17 @@ public static void Main() // public class HelpAttribute : Attribute { - string url; - string topic; - public HelpAttribute(string url) - { - this.url = url; - } + string _url; + string _topic; + + public HelpAttribute(string url) => _url = url; - public string Url => url; + public string Url => _url; public string Topic { - get { return topic; } - set { topic = value; } + get => _topic; + set => _topic = value; } } // @@ -105,7 +102,6 @@ private static void ReadAttributes() // Type widgetType = typeof(Widget); - //Gets every HelpAttribute defined for the Widget type object[] widgetClassAttributes = widgetType.GetCustomAttributes(typeof(HelpAttribute), false); if (widgetClassAttributes.Length > 0) @@ -116,7 +112,6 @@ private static void ReadAttributes() System.Reflection.MethodInfo displayMethod = widgetType.GetMethod(nameof(Widget.Display)); - //Gets every HelpAttribute defined for the Widget.Display method object[] displayMethodAttributes = displayMethod.GetCustomAttributes(typeof(HelpAttribute), false); if (displayMethodAttributes.Length > 0) diff --git a/docs/csharp/tour-of-csharp/snippets/shared/StackUsage.cs b/docs/csharp/tour-of-csharp/snippets/shared/StackUsage.cs index 9a721271bb906..fd5b6b53a9730 100644 --- a/docs/csharp/tour-of-csharp/snippets/shared/StackUsage.cs +++ b/docs/csharp/tour-of-csharp/snippets/shared/StackUsage.cs @@ -1,10 +1,11 @@ -using System; +using System; using Acme.Collections; + class Example { public static void Main() { - Stack s = new Stack(); + var s = new Stack(); s.Push(1); // stack contains 1 s.Push(10); // stack contains 1, 10 s.Push(100); // stack contains 1, 10, 100 diff --git a/docs/csharp/tour-of-csharp/snippets/shared/Types.cs b/docs/csharp/tour-of-csharp/snippets/shared/Types.cs index 2163fa269d0b5..b6196fbbfce9a 100644 --- a/docs/csharp/tour-of-csharp/snippets/shared/Types.cs +++ b/docs/csharp/tour-of-csharp/snippets/shared/Types.cs @@ -8,6 +8,7 @@ public struct Point { public double X { get; } public double Y { get; } + public Point(double x, double y) => (X, Y) = (x, y); } // @@ -17,31 +18,32 @@ namespace TourOfCsharp // public class Point { - public int x, y; - public Point(int x, int y) - { - this.x = x; - this.y = y; - } + public int X { get; } + public int Y { get; } + + public Point(int x, int y) => (X, Y) = (x, y); } // // public class Pair { - public TFirst First; - public TSecond Second; + public TFirst First { get; } + public TSecond Second { get; } + + public Pair(TFirst first, TSecond second) => + (First, Second) = (first, second); } // // public class Point3D : Point { - public int z; - public Point3D(int x, int y, int z) : - base(x, y) + public int Z { get; set; } + + public Point3D(int x, int y, int z) : base(x, y) { - this.z = z; + Z = z; } } // @@ -51,14 +53,17 @@ interface IControl { void Paint(); } + interface ITextBox : IControl { void SetText(string text); } + interface IListBox : IControl { void SetItems(string[] items); } + interface IComboBox : ITextBox, IListBox { } // @@ -67,6 +72,7 @@ interface IDataBound { void Bind(Binder b); } + public class EditBox : IControl, IDataBound { public void Paint() { } @@ -75,7 +81,6 @@ public void Bind(Binder b) { } // // - // A traditional enumeration of some root vegetables. public enum SomeRootVegetables { HorseRadish, @@ -85,7 +90,6 @@ public enum SomeRootVegetables // // - // A bit field or flag enumeration of harvesting seasons. [Flags] public enum Seasons { @@ -104,15 +108,15 @@ public static class Types public static void Examples() { // - Point p1 = new Point(0, 0); - Point p2 = new Point(10, 20); + var p1 = new Point(0, 0); + var p2 = new Point(10, 20); // // - Pair pair = new Pair { First = 1, Second = "two" }; - int i = pair.First; // TFirst is int - string s = pair.Second; // TSecond is string - // + var pair = new Pair(1, "two"); + int i = pair.First; // TFirst int + string s = pair.Second; // TSecond string + // // Point a = new Point(10, 20); diff --git a/docs/csharp/tour-of-csharp/types.md b/docs/csharp/tour-of-csharp/types.md index c1e03f4aabe9f..ddfbe901dffe2 100644 --- a/docs/csharp/tour-of-csharp/types.md +++ b/docs/csharp/tour-of-csharp/types.md @@ -13,7 +13,7 @@ New classes are created using class declarations. A class declaration starts wit - The attributes and modifiers of the class - The name of the class -- The base class (if given) +- The base class (when inheriting from a [base class](#base-classes)) - The interfaces implemented by the class. The header is followed by the class body, which consists of a list of member declarations written between the delimiters `{` and `}`. @@ -30,7 +30,7 @@ The memory occupied by an object is automatically reclaimed when the object is n ### Type parameters -Generic classes define [***type parameters***](programming-guide/generics/index.md). Type parameters are a list of type parameters names enclosed in angle brackets. Type parameters follow the class name. The type parameters can then be used in the body of the class declarations to define the members of the class. In the following example, the type parameters of `Pair` are `TFirst` and `TSecond`: +Generic classes define [***type parameters***](programming-guide/generics/index.md). Type parameters are a list of type parameter names enclosed in angle brackets. Type parameters follow the class name. The type parameters can then be used in the body of the class declarations to define the members of the class. In the following example, the type parameters of `Pair` are `TFirst` and `TSecond`: :::code language="csharp" source="./snippets/shared/Types.cs" ID="DefinePairClass"::: @@ -47,7 +47,7 @@ A class declaration may specify a base class. Follow the class name and type par :::code language="csharp" source="./snippets/shared/Types.cs" ID="Create3DPoint"::: -A class inherits the members of its base class. Inheritance means that a class implicitly contains almost all members of its base class. A class doesn't inherit the instance and static constructors, and the finalizer. A derived class can add new members to those members it inherits, but it can't remove the definition of an inherited member. In the previous example, `Point3D` inherits the `x` and `y` fields from `Point`, and every `Point3D` instance contains three fields, `x`, `y`, and `z`. +A class inherits the members of its base class. Inheritance means that a class implicitly contains almost all members of its base class. A class doesn't inherit the instance and static constructors, and the finalizer. A derived class can add new members to those members it inherits, but it can't remove the definition of an inherited member. In the previous example, `Point3D` inherits the `X` and `Y` members from `Point`, and every `Point3D` instance contains three properties, `X`, `Y`, and `Z`. An implicit conversion exists from a class type to any of its base class types. A variable of a class type can reference an instance of that class or an instance of any derived class. For example, given the previous class declarations, a variable of type `Point` can reference either a `Point` or a `Point3D`: @@ -81,7 +81,7 @@ An [***Enum***](../language-reference/builtin-types/enum.md) type defines a set :::code language="csharp" source="./snippets/shared/Types.cs" ID="EnumDeclaration"::: -You can also define an `enum` be used in combination as flags. The following declaration declares a set of flags for the four seasons. Any combination of the seasons may be applied, including an `All` value that includes all seasons: +You can also define an `enum` to be used in combination as flags. The following declaration declares a set of flags for the four seasons. Any combination of the seasons may be applied, including an `All` value that includes all seasons: :::code language="csharp" source="./snippets/shared/Types.cs" ID="FlagsEnumDeclaration"::: @@ -91,7 +91,7 @@ The following example shows declarations of both the preceding enums: ## Nullable types -Variables of any type may be declared as ***non-nullable*** or ***nullable***. A nullable variable can hold an additional `null` value, indicating no value. Nullable Value types (structs or enums) are represented by . Non-nullable and Nullable Reference types are both represented by the underlying reference type. The distinction is represented by metadata read by the compiler and some libraries. The compiler provides warnings when nullable references are de-referenced without first checking their value against `null`. The compiler also provides warnings when non-nullable references are assigned to a value that may be `null`. The following example declares a ***nullable int***, initializing it to `null`. Then, it sets the value to `5`. It demonstrates the same concept with a ***nullable string***. For more information, see [nullable value types](language-reference/builtin-types/nullable-value-types.md) and [nullable reference types](../nullable-references.md). +Variables of any type may be declared as ***non-nullable*** or ***nullable***. A nullable variable can hold an additional `null` value, indicating no value. Nullable Value types (structs or enums) are represented by . Non-nullable and Nullable Reference types are both represented by the underlying reference type. The distinction is represented by metadata read by the compiler and some libraries. The compiler provides warnings when nullable references are dereferenced without first checking their value against `null`. The compiler also provides warnings when non-nullable references are assigned to a value that may be `null`. The following example declares a ***nullable int***, initializing it to `null`. Then, it sets the value to `5`. It demonstrates the same concept with a ***nullable string***. For more information, see [nullable value types](language-reference/builtin-types/nullable-value-types.md) and [nullable reference types](../nullable-references.md). :::code language="csharp" source="./snippets/shared/Types.cs" ID="DeclareNullable"::: @@ -101,7 +101,7 @@ C# supports [***tuples***](../language-reference/builtin-types/value-tuples.md), :::code language="csharp" source="./snippets/shared/Types.cs" ID="DeclareTuples"::: -Tuples provide an alternative for data structure with multiple members, but doesn't use the building blocks described in the next article. +Tuples provide an alternative for data structure with multiple members, without using the building blocks described in the next article. >[!div class="step-by-step"] >[Previous](index.md) From 283942b68b20f9a9764e073d030edac87e07f9fb Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Mon, 10 Aug 2020 11:37:53 -0400 Subject: [PATCH 11/11] respond to feedbck And fix build warnings that crept in. --- docs/csharp/tour-of-csharp/features.md | 4 +-- docs/csharp/tour-of-csharp/index.md | 4 +-- .../tour-of-csharp/program-building-blocks.md | 30 +++++++++---------- .../snippets/shared/AcmeStack.cs | 4 +-- .../snippets/shared/ClassesObjects.cs | 16 +++++----- .../snippets/shared/Features.cs | 8 +++-- docs/csharp/tour-of-csharp/types.md | 8 ++--- .../MakeConst/AnalyzerReleases.Shipped.md | 3 -- .../MakeConst/AnalyzerReleases.Unshipped.md | 3 -- 9 files changed, 39 insertions(+), 41 deletions(-) delete mode 100644 samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Shipped.md delete mode 100644 samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Unshipped.md diff --git a/docs/csharp/tour-of-csharp/features.md b/docs/csharp/tour-of-csharp/features.md index fd4ad5786f334..72d0294520ef7 100644 --- a/docs/csharp/tour-of-csharp/features.md +++ b/docs/csharp/tour-of-csharp/features.md @@ -7,7 +7,7 @@ ms.date: 08/06/2020 ## Arrays, collections, and LINQ -C# and .NET provide many different collection types. Arrays have syntax defined by the language. General collection types are listed in the namespace. Specialized collections include for accessing continuous memory on the stack frame, and for accessing continuous memory on the managed heap. All collections, including arrays, , and share a unifying principle for iteration. You use the interface. This unifying principle means that any of the collection types can be used with LINQ queries or other algorithms. You write methods using and those algorithms work with any collection. +C# and .NET provide many different collection types. Arrays have syntax defined by the language. Generic collection types are listed in the namespace. Specialized collections include for accessing continuous memory on the stack frame, and for accessing continuous memory on the managed heap. All collections, including arrays, , and share a unifying principle for iteration. You use the interface. This unifying principle means that any of the collection types can be used with LINQ queries or other algorithms. You write methods using and those algorithms work with any collection. ### Arrays @@ -98,7 +98,7 @@ The following example declares a `HelpAttribute` attribute that can be placed on :::code language="csharp" source="./snippets/shared/Features.cs" ID="DefineAttribute"::: -All attribute classes derive from the base class provided by the standard library. Attributes can be applied by giving their name, along with any arguments, inside square brackets just before the associated declaration. If an attribute’s name ends in `Attribute`, that part of the name can be omitted when the attribute is referenced. For example, the `HelpAttribute` can be used as follows. +All attribute classes derive from the base class provided by the .NET library. Attributes can be applied by giving their name, along with any arguments, inside square brackets just before the associated declaration. If an attribute’s name ends in `Attribute`, that part of the name can be omitted when the attribute is referenced. For example, the `HelpAttribute` can be used as follows. :::code language="csharp" source="./snippets/shared/Features.cs" ID="UseAttributes"::: diff --git a/docs/csharp/tour-of-csharp/index.md b/docs/csharp/tour-of-csharp/index.md index 8d5acf7d610bd..a99316eb5dff2 100644 --- a/docs/csharp/tour-of-csharp/index.md +++ b/docs/csharp/tour-of-csharp/index.md @@ -22,7 +22,7 @@ The "Hello, World" program is traditionally used to introduce a programming lang The "Hello, World" program starts with a `using` directive that references the `System` namespace. Namespaces provide a hierarchical means of organizing C# programs and libraries. Namespaces contain types and other namespaces—for example, the `System` namespace contains a number of types, such as the `Console` class referenced in the program, and a number of other namespaces, such as `IO` and `Collections`. A `using` directive that references a given namespace enables unqualified use of the types that are members of that namespace. Because of the `using` directive, the program can use `Console.WriteLine` as shorthand for `System.Console.WriteLine`. -The `Hello` class declared by the "Hello, World" program has a single member, the method named `Main`. The `Main` method is declared with the `static` modifier. While instance methods can reference a particular enclosing object instance using the keyword `this`, static methods operate without reference to a particular object. By convention, a static method named `Main` serves as the entry point of a program. +The `Hello` class declared by the "Hello, World" program has a single member, the method named `Main`. The `Main` method is declared with the `static` modifier. While instance methods can reference a particular enclosing object instance using the keyword `this`, static methods operate without reference to a particular object. By convention, a static method named `Main` serves as the entry point of a C# program. The output of the program is produced by the `WriteLine` method of the `Console` class in the `System` namespace. This class is provided by the standard class libraries, which, by default, are automatically referenced by the compiler. @@ -104,7 +104,7 @@ There are several kinds of *variables* in C#, including fields, array elements, ## Program structure -The key organizational concepts in C# are [***programs***](../programming-guide/inside-a-program.md), [***namespaces***](../programming-guide/concepts/namespaces/index.md), [***types***](../programming-guide/concepts/types/index.md), [***members***](../programming-guide/classes-and-structs/members.md), and [***assemblies***](../../standard/assembly.md). Programs declare types, which contain members and can be organized into namespaces. Classes, structs, and interfaces are examples of types. Fields, methods, properties, and events are examples of members. When C# programs are compiled, they're physically packaged into assemblies. Assemblies typically have the file extension `.exe` or `.dll`, depending on whether they implement ***applications*** or ***libraries***, respectively. +The key organizational concepts in C# are [***programs***](../programming-guide/inside-a-program/index.md), [***namespaces***](../programming-guide/namespaces/index.md), [***types***](../programming-guide/types/index.md), [***members***](../programming-guide/classes-and-structs/members.md), and [***assemblies***](../../standard/assembly/index.md). Programs declare types, which contain members and can be organized into namespaces. Classes, structs, and interfaces are examples of types. Fields, methods, properties, and events are examples of members. When C# programs are compiled, they're physically packaged into assemblies. Assemblies typically have the file extension `.exe` or `.dll`, depending on whether they implement ***applications*** or ***libraries***, respectively. As a small example, consider an assembly that contains the following code: diff --git a/docs/csharp/tour-of-csharp/program-building-blocks.md b/docs/csharp/tour-of-csharp/program-building-blocks.md index 1c6cf1070b077..1218cff3c45fc 100644 --- a/docs/csharp/tour-of-csharp/program-building-blocks.md +++ b/docs/csharp/tour-of-csharp/program-building-blocks.md @@ -14,8 +14,8 @@ The members of a `class` are either ***static members*** or ***instance members* The following list provides an overview of the kinds of members a class can contain. - **Constants**: Constant values associated with the class -- **Fields**: of the class -- **Methods**: and actions that can be performed by the class +- **Fields**: Variables that are associated of the class +- **Methods**: Actions that can be performed by the class - **Properties**: Actions associated with reading and writing named properties of the class - **Indexers**: Actions associated with indexing instances of the class like an array - **Events**: Notifications that can be generated by the class @@ -29,11 +29,11 @@ The following list provides an overview of the kinds of members a class can cont Each member of a class has an associated accessibility, which controls the regions of program text that can access the member. There are six possible forms of accessibility. The access modifiers are summarized below. - `public`: Access isn't limited. +- `private`: Access is limited to this class. - `protected`: Access is limited to this class or classes derived from this class. - `internal`: Access is limited to the current assembly (`.exe` or `.dll`). -- `protected internal`: Access is limited to the containing class, classes derived from the containing class, or classes within the same assembly. -- `private`: Access is limited to this class. -- `private protected`: Access is limited to the containing class or classes derived from the containing type within the same assembly. +- `protected internal`: Access is limited to this class, classes derived from this class, or classes within the same assembly. +- `private protected`: Access is limited to this class or classes derived from this type within the same assembly. ## Fields @@ -59,6 +59,12 @@ Like types, methods may also have a set of type parameters, for which type argum The *signature* of a method must be unique in the class in which the method is declared. The signature of a method consists of the name of the method, the number of type parameters, and the number, modifiers, and types of its parameters. The signature of a method doesn't include the return type. +When a method body is a single expression, the method can be defined using a compact expression format, as shown in the following example: + +```csharp +public override ToString() => "This is an object"; +``` + ### Parameters Parameters are used to pass values or variable references to methods. The parameters of a method get their actual values from the *arguments* that are specified when the method is invoked. There are four kinds of parameters: value parameters, reference parameters, output parameters, and parameter arrays. @@ -109,9 +115,9 @@ The following `Entity` class has both static and instance members. :::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="EntityClass"::: -Each `Entity` instance contains a serial number (and presumably some other information that isn't shown here). The `Entity` constructor (which is like an instance method) initializes the new instance with the next available serial number. Because the constructor is an instance member, it's permitted to access both the `serialNo` instance field and the `nextSerialNo` static field. +Each `Entity` instance contains a serial number (and presumably some other information that isn't shown here). The `Entity` constructor (which is like an instance method) initializes the new instance with the next available serial number. Because the constructor is an instance member, it's permitted to access both the `_serialNo` instance field and the `s_nextSerialNo` static field. -The `GetNextSerialNo` and `SetNextSerialNo` static methods can access the `nextSerialNo` static field, but it would be an error for them to directly access the `serialNo` instance field. +The `GetNextSerialNo` and `SetNextSerialNo` static methods can access the `s_nextSerialNo` static field, but it would be an error for them to directly access the `_serialNo` instance field. The following example shows the use of the `Entity` class. @@ -221,13 +227,13 @@ An *operator* is a member that defines the meaning of applying a particular expr The `MyList` class declares two operators, `operator ==` and `operator !=`. These overridden operators give new meaning to expressions that apply those operators to `MyList` instances. Specifically, the operators define equality of two `MyList` instances as comparing each of the contained objects using their `Equals` methods. The following example uses the `==` operator to compare two `MyList` instances. -:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="ListAccess"::: +:::code language="csharp" source="./snippets/shared/ClassesObjects.cs" ID="ListAddition"::: The first `Console.WriteLine` outputs `True` because the two lists contain the same number of objects with the same values in the same order. Had `MyList` not defined `operator ==`, the first `Console.WriteLine` would have output `False` because `a` and `b` reference different `MyList` instances. ### Finalizers -A *finalizer* is a member that implements the actions required to finalize an instance of a class. Finalizers can't have parameters, they can't have accessibility modifiers, and they can't be invoked explicitly. The finalizer for an instance is invoked automatically during garbage collection. +A *finalizer* is a member that implements the actions required to finalize an instance of a class. Typically, a finalizer is needed to release unmanaged resources. Finalizers can't have parameters, they can't have accessibility modifiers, and they can't be invoked explicitly. The finalizer for an instance is invoked automatically during garbage collection. For more details, see the article on [finalizers](../programming-guide/classes-and-structs/destructors.md). The garbage collector is allowed wide latitude in deciding when to collect objects and run finalizers. Specifically, the timing of finalizer invocations isn't deterministic, and finalizers may be executed on any thread. For these and other reasons, classes should implement finalizers only when no other solutions are feasible. @@ -288,12 +294,6 @@ The following lists the kinds of statements that can be used: * `lock` statement. * `using` statement. -When a method body is a single expression, the method can be defined using a compact expression format, as shown in the following example: - -```csharp -public override ToString() => "This is an object"; -``` - >[!div class="step-by-step"] >[Previous](types.md) >[Next](features.md) diff --git a/docs/csharp/tour-of-csharp/snippets/shared/AcmeStack.cs b/docs/csharp/tour-of-csharp/snippets/shared/AcmeStack.cs index bcf4da19e2f56..b36528952627f 100644 --- a/docs/csharp/tour-of-csharp/snippets/shared/AcmeStack.cs +++ b/docs/csharp/tour-of-csharp/snippets/shared/AcmeStack.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Acme.Collections { @@ -8,7 +8,7 @@ public class Stack public void Push(T data) { - _top = new Entry(top, data); + _top = new Entry(_top, data); } public T Pop() diff --git a/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs b/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs index debc3924e4600..0f13c56890a0d 100644 --- a/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs +++ b/docs/csharp/tour-of-csharp/snippets/shared/ClassesObjects.cs @@ -114,7 +114,7 @@ public VariableReference(string name) public override double Evaluate(Dictionary vars) { - object value = vars[name] ?? throw new Exception($"Unknown variable: {name}"); + object value = vars[_name] ?? throw new Exception($"Unknown variable: {_name}"); return Convert.ToDouble(value); } } @@ -136,7 +136,7 @@ public override double Evaluate(Dictionary vars) { double x = _left.Evaluate(vars); double y = _right.Evaluate(vars); - switch (op) + switch (_op) { case '+': return x + y; case '-': return x - y; @@ -197,7 +197,7 @@ public int Capacity if (value != _items.Length) { T[] newItems = new T[value]; - Array.Copy(_items, 0, newItems, 0, count); + Array.Copy(_items, 0, newItems, 0, _count); _items = newItems; } } @@ -216,7 +216,7 @@ public T this[int index] public void Add(T item) { if (_count == Capacity) Capacity = _count * 2; - items[_count] = item; + _items[_count] = item; _count++; OnChanged(); } @@ -229,11 +229,11 @@ public override bool Equals(object other) => static bool Equals(MyList a, MyList b) { if (Object.ReferenceEquals(a, null)) return Object.ReferenceEquals(b, null); - if (Object.ReferenceEquals(b, null) || a.count != b.count) + if (Object.ReferenceEquals(b, null) || a._count != b._count) return false; - for (int i = 0; i < a.count; i++) + for (int i = 0; i < a._count; i++) { - if (!object.Equals(a.items[i], b.items[i])) + if (!object.Equals(a._items[i], b._items[i])) { return false; } @@ -268,7 +268,7 @@ public static void Usage() names.Add("Liz"); names.Add("Martha"); names.Add("Beth"); - Console.WriteLine(changeCount); // "3" + Console.WriteLine(s_changeCount); // "3" } } // diff --git a/docs/csharp/tour-of-csharp/snippets/shared/Features.cs b/docs/csharp/tour-of-csharp/snippets/shared/Features.cs index 3e7e665ff2d45..eccf3efebbc58 100644 --- a/docs/csharp/tour-of-csharp/snippets/shared/Features.cs +++ b/docs/csharp/tour-of-csharp/snippets/shared/Features.cs @@ -77,7 +77,11 @@ public static void Examples() var weatherData = (Date: DateTime.Now, LowTemp: 5, HighTemp: 30); // - Console.WriteLine($"The low and high temperature on {weatherData.Date:MM-DD-YYYY} was {weatherData.LowTemp} and {weatherData.HighTemp}"); + Console.WriteLine($"The low and high temperature on {weatherData.Date:MM-DD-YYYY}"); + Console.WriteLine($" was {weatherData.LowTemp} and {weatherData.HighTemp}."); + // Output (similar to): + // The low and high temperature on 08-11-2020 + // was 5 and 30. // DelegateExample.Main(); @@ -89,7 +93,7 @@ public static void Examples() public async Task RetrieveDocsHomePage() { var client = new HttpClient(); - byte[] content = await client.GetByteArrayAsync("https://docs.microsoft.com/en-us/"); + byte[] content = await client.GetByteArrayAsync("https://docs.microsoft.com/"); Console.WriteLine($"{nameof(RetrieveDocsHomePage)}: Finished downloading."); return content.Length; diff --git a/docs/csharp/tour-of-csharp/types.md b/docs/csharp/tour-of-csharp/types.md index ddfbe901dffe2..ecc47860558f0 100644 --- a/docs/csharp/tour-of-csharp/types.md +++ b/docs/csharp/tour-of-csharp/types.md @@ -7,7 +7,7 @@ ms.date: 08/06/2020 ## Classes and objects -*Classes* are the most fundamental of C#’s types. A class is a data structure that combines state (fields) and actions (methods and other function members) in a single unit. A class provides a definition for dynamically created *instances* of the class, also known as *objects*. Classes support *inheritance* and *polymorphism*, mechanisms whereby *derived classes* can extend and specialize *base classes*. +*Classes* are the most fundamental of C#’s types. A class is a data structure that combines state (fields) and actions (methods and other function members) in a single unit. A class provides a definition for *instances* of the class, also known as *objects*. Classes support *inheritance* and *polymorphism*, mechanisms whereby *derived classes* can extend and specialize *base classes*. New classes are created using class declarations. A class declaration starts with a header. The header specifies: @@ -30,7 +30,7 @@ The memory occupied by an object is automatically reclaimed when the object is n ### Type parameters -Generic classes define [***type parameters***](programming-guide/generics/index.md). Type parameters are a list of type parameter names enclosed in angle brackets. Type parameters follow the class name. The type parameters can then be used in the body of the class declarations to define the members of the class. In the following example, the type parameters of `Pair` are `TFirst` and `TSecond`: +Generic classes define [***type parameters***](../programming-guide/generics/index.md). Type parameters are a list of type parameter names enclosed in angle brackets. Type parameters follow the class name. The type parameters can then be used in the body of the class declarations to define the members of the class. In the following example, the type parameters of `Pair` are `TFirst` and `TSecond`: :::code language="csharp" source="./snippets/shared/Types.cs" ID="DefinePairClass"::: @@ -61,7 +61,7 @@ Classes define types that support inheritance and polymorphism. They enable you ## Interfaces -An [***interface***](programming-guide/interfaces/index.md) defines a contract that can be implemented by classes and structs. An interface can contain methods, properties, events, and indexers. An interface typically doesn't provide implementations of the members it defines—it merely specifies the members that must be supplied by classes or structs that implement the interface. +An [***interface***](../programming-guide/interfaces/index.md) defines a contract that can be implemented by classes and structs. An interface can contain methods, properties, events, and indexers. An interface typically doesn't provide implementations of the members it defines—it merely specifies the members that must be supplied by classes or structs that implement the interface. Interfaces may employ ***multiple inheritance***. In the following example, the interface `IComboBox` inherits from both `ITextBox` and `IListBox`. @@ -91,7 +91,7 @@ The following example shows declarations of both the preceding enums: ## Nullable types -Variables of any type may be declared as ***non-nullable*** or ***nullable***. A nullable variable can hold an additional `null` value, indicating no value. Nullable Value types (structs or enums) are represented by . Non-nullable and Nullable Reference types are both represented by the underlying reference type. The distinction is represented by metadata read by the compiler and some libraries. The compiler provides warnings when nullable references are dereferenced without first checking their value against `null`. The compiler also provides warnings when non-nullable references are assigned to a value that may be `null`. The following example declares a ***nullable int***, initializing it to `null`. Then, it sets the value to `5`. It demonstrates the same concept with a ***nullable string***. For more information, see [nullable value types](language-reference/builtin-types/nullable-value-types.md) and [nullable reference types](../nullable-references.md). +Variables of any type may be declared as ***non-nullable*** or ***nullable***. A nullable variable can hold an additional `null` value, indicating no value. Nullable Value types (structs or enums) are represented by . Non-nullable and Nullable Reference types are both represented by the underlying reference type. The distinction is represented by metadata read by the compiler and some libraries. The compiler provides warnings when nullable references are dereferenced without first checking their value against `null`. The compiler also provides warnings when non-nullable references are assigned to a value that may be `null`. The following example declares a ***nullable int***, initializing it to `null`. Then, it sets the value to `5`. It demonstrates the same concept with a ***nullable string***. For more information, see [nullable value types](../language-reference/builtin-types/nullable-value-types.md) and [nullable reference types](../nullable-references.md). :::code language="csharp" source="./snippets/shared/Types.cs" ID="DeclareNullable"::: diff --git a/samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Shipped.md b/samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Shipped.md deleted file mode 100644 index d567f14248eff..0000000000000 --- a/samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Shipped.md +++ /dev/null @@ -1,3 +0,0 @@ -; Shipped analyzer releases -; https://github.com/dotnet/roslyn-analyzers/blob/master/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md - diff --git a/samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Unshipped.md b/samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Unshipped.md deleted file mode 100644 index 43574499f9ea2..0000000000000 --- a/samples/snippets/csharp/roslyn-sdk/Tutorials/MakeConst/MakeConst/AnalyzerReleases.Unshipped.md +++ /dev/null @@ -1,3 +0,0 @@ -; Unshipped analyzer release -; https://github.com/dotnet/roslyn-analyzers/blob/master/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md -