Training - Beratung - Projektarbeiten

www.David-Tielke.de

Webcast C# 6.0 - Folge 5: Null Conditional Operator

Robusten Code zu schreiben ist nicht besonders schwer, aber mühsam. Neben vielen Fehlern die in einer Anwendung auftreten können, ist die NullReferenceException wahrscheinlich die am häufigst auftretende und wohl auch nervigste Ausnahme die es gibt. Will man diese vermeiden, muss theoretisch jede Referenz auf die Ungleichheit mit null überprüft werden, bevor darauf zugegriffen wird. Auch wenn dies recht einfach möglich ist, sorgen die vielen Überprüfungen und die damit einhergehenden Verzweigungen für sehr komplexen Code der schwierig zu überblicken ist. Mit C# 6.0 wurde mit dem “Null Conditional Operator” ein spezieller Operator eingeführt, die das schreiben von robusterem Code sehr einfach macht. Welche Möglichkeiten der Operator bietet, was damit angestellt werden kann und wann er den Code eher schlechter als besser lesbar macht, zeige ich im fünften Teil dieser Webcastserie.

Dazu aus der Project Roslyn Webseite:

Sometimes code tends to drown a bit in null-checking. The null-conditional operator lets you access members and elements only when the receiver is not-null, providing a null result otherwise:
int? length = customers?.Length; // null if customers is null
Customer first = customers?[0];  // null if customers is null
The null-conditional operator is conveniently used together with the null coalescing operator ?? :
int length = customers?.Length ?? 0; // 0 if customers is null
The null-conditional operator exhibits short-circuiting behavior, where an immediately following chain of member accesses, element accesses and invocations will only be executed if the original receiver was not null:
int? first = customers?[0].Orders.Count();
This example is essentially equivalent to:
int? first = (customers != null) ? customers[0].Orders.Count() : null;
Except that customers is only evaluated once. None of the member accesses, element accesses and invocations immediately following the ? are executed unless customers has a non-null value. Of course null-conditional operators can themselves be chained, in case there is a need to check for null more than once in a chain:
int? first = customers?[0].Orders?.Count();
Note that an invocation (a parenthesized argument list) cannot immediately follow the ? operator – that would lead to too many syntactic ambiguities. Thus, the straightforward way of calling a delegate only if it’s there does not work. However, you can do it via the Invoke method on the delegate:
if (predicate?.Invoke(e) ?? false) { … }
We expect that a very common use of this pattern will be for triggering events:
PropertyChanged?.Invoke(this, args);
This is an easy and thread-safe way to check for null before you trigger an event. The reason it’s thread-safe is that the feature evaluates the left-hand side only once, and keeps it in a temporary variable.
Links

Webcast C# 6.0 - Folge 4: Using Static

Die wohl merkwürdigste Erweiterung von C# 6.0 ist ohne Zweifel “Using Static”, also das direkte Einbinden von Membern eines statischen Typs in einen Namensraum. Dadurch entfällt der vermeidlich komplizierte Aufruf über den Klassennamen. Auch wenn ich ein großer Fan von C# 6.0 und dessen Erweiterungen bin, kann ich diesem Sprachfeature einfach nichts abgewinnen. Der Code dadurch mag kompakter werden, jedoch leidet die Lesbarkeit des Codes sehr stark und statische Member aus anderen Klassen sehen plötzlich so aus, wie Memberaufrufe auf dem aktuellen Typ – ein no-go!

Dazu aus der Project Roslyn Webseite

The feature allows all the accessible static members of a type to be imported, making them available without qualification in subsequent code:
using static System.Console;
using static System.Math;
using static System.DayOfWeek;
class Program
{
    static void Main()
    {
        WriteLine(Sqrt(3*3 + 4*4)); 
        WriteLine(Friday - Monday); 
    }
}
This is great for when you have a set of functions related to a certain domain that you use all the time. System.Math would be a common example of that. It also lets you directly specify the individual named values of an enum type, like the System.DayOfWeek members above. Extension methods Extension methods are static methods, but are intended to be used as instance methods. Instead of bringing extension methods into the global scope, the using static feature makes the extension methods of the type available as extension methods:
using static System.Linq.Enumerable; // The type, not the namespace
{
    static void Main()
    {
        var range = Range(5, 17);                // Ok: not extension
        var odd = Where(range, i => i % 2 == 1); // Error, not in scope
        var even = range.Where(i => i % 2 == 0); // Ok
    }
}
This does mean that it can now be a breaking change to turn an ordinary static method into an extension method, which was not the case before. But extension methods are generally only called as static methods in the rare cases where there is an ambiguity. In those cases, it seems right to require full qualification of the method anyway.
Links

Webcast C# 6.0 – Folge 2: Read Only Auto Properties

Einer der Erweiterungen in C# 6.0, die sehr viel boilerplated Code vermeiden können, sind die Read Only Auto Properties.

Im zweiten Teil der Webcastreihe zu den Erweiterungen aus C# 6.0, widmen wir uns dieser genialien kleinen Erweiterung und zeigen wo sie eingesetzt werden sollte und wo nicht.

Dazu aus der Dokumentation des Roslyn-Projektes:

Auto-properties can now be declared without a setter.
public class Customer
{
    public string First { get; } = "Jane";
    public string Last { get; } = "Doe";
}
The backing field of a getter-only auto-property is implicitly declared as readonly (though this matters only for reflection purposes). It can be initialized through an initializer on the property as in the example above. Also, a getter-only property can be assigned to in the declaring type’s constructor body, which causes the value to be assigned directly to the underlying field:
public class Customer
{
    public string Name { get; }
    public Customer(string first, string last)
    {
        Name = first + " " + last;
    }
}
This is about expressing types more concisely, but note that it also removes an important difference in the language between mutable and immutable types: auto-properties were a shorthand available only if you were willing to make your class mutable, and so the temptation to default to that was great. Now, with getter-only auto-properties, the playing field has been leveled between mutable and immutable.

 

Links