Dawno nie było nic .NETowego. Pora więc to nadrobić informacjami o tym co znajdziemy w nowej wersji C# – wersji 7. Większość rzeczy można już przetestować w Visual Studio 15 preview. Ale jak to z tego typu oprogramowaniem. Lepiej na wirtualce albo na kompie który ma być zaraz zaorany :)

Z cyklu nowości w C# 7, do tej pory ukazały się artykuły:

  1. C# 7: Tuples
  2. C# 7: Pattern Matching
  3. C# 7: out i ref
  4. C# 7: Funkcje lokalne
  5. C# 7: Lukier składniowy

Side node: wszystkie przykłady zostały przetestowane na VS 2017 RC.

Uwaga: Cały artykuł bazuje na VS 15 Preview 5. Wszystkie przykłady kodu, użyte tutaj działają na Preview 5 z targetem .NET Framework 4.6.2 + dodatkami o którym mowa w tekście. Wiem, że możliwe iż z rana będzie dostępna wersja VS 15 RTM która może zostać zaraz ogłoszona na connect(). Ale nic na to nie poradzę :( Postaram się jednak zaktualizować ten post jak tylko będę wiedział, co się zmieniło i czy cokolwiek się zmieniło. connect() się skończył tym, że mamy VS 2017 w wersji RC. Na tej wersji, przykłady poniżej działają.

Na pierwszy ogień chciałbym poruszyć Tuples. Nie te, które już są Tuple<T1, T1…> a nowe, które są dużo fajniejsze i zwą się ValueTuple :) Przynajmniej przy Preview 5, by z nich skorzystać trzeba było zainstalować nuget package System.ValueTuple w pre-release mode.

Kiedyś tuple, tworzyliśmy w następujący sposób:

var oldWay  = Tuple.Create("Jakub", 34);

Co dawało nam dostęp do elementów poprzez Item1 i Item2. Po zainstalowaniu paczki System.ValueTuple, to samo, możemy zapisać tak:

var newWay  = ("Jakub", 34);

Ale, tak jak za pierwszym razem, tak i za drugim, nie wiemy co to jest "Jakub" i co to jest to 34. Musimy zawsze wracać do jakiejś dokumentacji czy też implementacji danej metody by się dowiedzieć o co chodzi. By uniknąć takich problemów możemy wartością nadać nazwę:

var newWayNamed = (name: "Jakub", age: 34);

Teraz już nie tylko możemy odwołać się poprzez Item1 czy Item2 ale też poprzez name i age. Do tego funkcje mogą zwracać nowe nowe tuples:

public (int, int) SomeFunction() {}
public (string name, int age) GetInfo(Guid id) {}

za pomocą:

return (10, 10);
return (name: personName, age: personAge);

Na razie to tylko takie… ła, ok, i? nazywamy i co, no, to, że teraz też możemy to robić. Tuple stają się bardziej przyjazne i przyjemne i nie trzeba wykorzystywać Tuple.Create co było dość męczące. No i w końcu jest możliwość obejścia Item1, Item2, Item3Item10

Dodatkowo w C# 7, będzie możliwość przypisania istniejącego tuple czy też obiektu pod zmienne lokalne. Dla przykładu powyższy kod możemy rozbić na zmienne name i age w następujący sposób:

(var name, var age) = newWayNamed ;
var (name, age) = newWayNamed ;

string name; int age;
(name, age) = newWayNamed ;

W Elixir taką opcję nazwalibyśmy pattern matching, tutaj nazywa się to deconstructing assignment :) Ta opcja już jest fajna i ciekawa, w szczególności iż napisałem, że możemy ją stosować do obiektów. A to znaczy, że każdy obiekt który będzie implementował metodę:

public void Deconstruct(out T1 x1…) {}

Czy też extension method:

public static void Deconstruct(this T p, out T1 x1 …)

Będzie mógł ulec dekonstrukcji na zmienne. Na przykład:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public Person(string name, int age)
    {
        this.Name = name;
        this.Age = age;
    }

    public void Deconstruct(out string name, out int age)
    {
        age = this.Age ;
        name = this.Name;
    }
}

// or

public static class DeconstructTest
{
    public static void Deconstruct(this Person p, out string name, out int age)
    {
        name = p.Name;
        age = p.Age;
    }
}

// then

var p = new Person("Jakub", 34);
var (name, age) = p;

To tyle jeżeli chodzi o tuples. Jak dla mnie jest to krok do przodu i w końcu tuples zaczynają się do czegoś przydawać. Tak naprawdę już samo nazwanie poszczególnych elementów dużo daje. Cała reszta to miły lukier składniowy, który nie powiem, dużo daje :)

5 KOMENTARZE

  1. Oj idzie w stronę balaganiarstwa, ja zdecydowanie nie przepadalem za tuplami, zawsze tworzylem klasę. Jezeli cos nie jest warte aby posiadalo wlasna klasę to znaczy ze mamy zly model.

    Zdecydowanie będzie to zbawienie dla miłośników zwracania wartości przez out – a zwroce sobie cos dodatkowego mimo tego ze logicznie nie powinno tego tutaj być.

    No ale zobaczymy w praktyce, moze taki stary dziad jak ja polubi tez takie rozwiązanie ;)

    • ;) czymś będzie, czym to dobre pytanie :) na pewno będzie szedł w bardziej języki funkcyjne zachowując przy tym obiektowość. Ciekawe jak im to wyjdzie :)

      • W tę samą stronę (tylko odwrotnie) idą języki funkcyjne (ES6). W końcu gdzieś się spotkają :)

Comments are closed.