OSDN Git Service

Regular updates
[twpd/master.git] / csharp7.md
1 ---
2 title: C# 7
3 category: C-like
4 updated: 2018-12-06
5 layout: 2017/sheet
6 prism_languages: [csharp]
7 description: |
8   A quick overview of C# 7
9 ---
10
11 ### Out Variables
12
13 ```csharp
14 public void PrintCoordinates(Point p)
15 {
16     p.GetCoordinates(out int x, out int y);
17     WriteLine($"({x}, {y})");
18 }
19 ```
20
21 `out` is used to declare a variable at the point where it is passed as an argument.
22
23 ### Pattern Matching
24
25 #### Is-expressions with patterns
26
27 ```csharp
28 public void PrintStars(object o)
29 {
30     if (o is null) return;     // constant pattern "null"
31     if (!(o is int i)) return; // type pattern "int i"
32     WriteLine(new string('*', i));
33 }
34 ```
35
36 #### Switch statements with patterns
37
38 ```csharp
39 switch(shape)
40 {
41     case Circle c:
42         WriteLine($"circle with radius {c.Radius}");
43         break;
44     case Rectangle s when (s.Length == s.Height):
45         WriteLine($"{s.Length} x {s.Height} square");
46         break;
47     case Rectangle r:
48         WriteLine($"{r.Length} x {r.Height} rectangle");
49         break;
50     default:
51         WriteLine("<unknown shape>");
52         break;
53     case null:
54         throw new ArgumentNullException(nameof(shape));
55 }
56 ```
57
58 ### Tuples
59
60 #### Tuple type
61
62 ```csharp
63 (string, string, string) LookupName(long id) // tuple return type
64 {
65     ... // retrieve first, middle and last from data storage
66     return (first, middle, last); // tuple literal
67 }
68 ```
69
70 ```csharp
71 var names = LookupName(id);
72 WriteLine($"found {names.Item1} {names.Item3}.");
73 ```
74
75 #### Tuple elements with name
76
77 ```csharp
78 (string first, string middle, string last) LookupName(long id) // tuple elements have names
79 ```
80
81 ```csharp
82 var names = LookupName(id);
83 WriteLine($"found {names.first} {names.last}.");
84 ```
85
86 #### Tuple Literals
87
88 ```csharp
89    return (first: first, middle: middle, last: last); // named tuple elements in a literal
90 ```
91
92 #### Tuple Deconstruction
93
94 ```csharp
95 (var first, var middle, var last) = LookupName(id1);
96 WriteLine($"found {first} {last}.");
97 ```
98 or
99 ```csharp
100 var (first, middle, last) = LookupName(id1); // var outside
101 ```
102 or
103 ```csharp
104 (first, middle, last) = LookupName(id2); // assign onto existing variables
105 ```
106
107
108 ### Local Functions
109
110 ```csharp
111 public int Fibonacci(int x)
112 {
113     if (x < 0) throw new ArgumentException("Less negativity please!", nameof(x));
114     return Fib(x).current;
115
116     (int current, int previous) Fib(int i)
117     {
118         if (i == 0) return (1, 0);
119         var (p, pp) = Fib(i - 1);
120         return (p + pp, p);
121     }
122 }
123 ```
124
125 ### Literal Improvements
126
127 #### Digit Separator inside numbers literals
128
129 ```csharp
130 var d = 123_456;
131 var x = 0xAB_CD_EF;
132 ```
133
134 #### Binary Literals
135
136 ```csharp
137 var b = 0b1010_1011_1100_1101_1110_1111;
138 ```
139
140 ### Ref Returns and Locals
141
142 ```csharp
143 public ref int Find(int number, int[] numbers)
144 {
145     for (int i = 0; i < numbers.Length; i++)
146     {
147         if (numbers[i] == number) 
148         {
149             return ref numbers[i]; // return the storage location, not the value
150         }
151     }
152     throw new IndexOutOfRangeException($"{nameof(number)} not found");
153 }
154
155 int[] array = { 1, 15, -39, 0, 7, 14, -12 };
156 ref int place = ref Find(7, array); // aliases 7's place in the array
157 place = 9; // replaces 7 with 9 in the array
158 WriteLine(array[4]); // prints 9
159 ```
160
161 ### More Expression Bodied Members
162
163 C# 7.0 adds accessors, constructors and finalizers to the list of things that can have expression bodies:
164
165 ```csharp
166 class Person
167 {
168     private static ConcurrentDictionary<int, string> names = new ConcurrentDictionary<int, string>();
169     private int id = GetId();
170
171     public Person(string name) => names.TryAdd(id, name); // constructors
172     ~Person() => names.TryRemove(id, out *);              // destructors
173     public string Name
174     {
175         get => names[id];                                 // getters
176         set => names[id] = value;                         // setters
177     }
178 }
179 ```
180
181 ### Throw Expressions 
182
183 ```csharp
184 class Person
185 {
186     public string Name { get; }
187     public Person(string name) => Name = name ?? throw new ArgumentNullException(name);
188     public string GetFirstName()
189     {
190         var parts = Name.Split(" ");
191         return (parts.Length > 0) ? parts[0] : throw new InvalidOperationException("No name!");
192     }
193     public string GetLastName() => throw new NotImplementedException();
194 }
195 ```