c# 6.0–inicjalizacja słowników oraz automatycznych właściwości

Najpierw zobaczymy, jak mogła wyglądać inicjalizacja słownika przed wersją 6.0:

var data = new Dictionary<string, int>()
{
 {"Klucz1",1 },
 {"Klucz2",114 },
 {"Klucz3",114 },
 {"Klucz5",41 }
};

Składnia trochę ciężka w czytaniu. W C# 6.0 możliwe będzie:

var data = new Dictionary<string, int>()
{
 ["Klucz1"] = 1,
 ["Klucz2"] = 114,
 ["Klucz3"] = 114,
 ["Klucz5"] = 41
};

Moim zdaniem dużo lepiej to wygląda. Drobna zmiana, a zwiększa czytelność kodu.

Kolejna natomiast zmiana nie podoba mi się i na szczęście została wycofana. Chciano wprowadzić nowy sposób uzyskiwania dostępu do pól. Klasycznie można odczytać wartość za pomocą:

var data = new Dictionary<string, int>()
{
    ["Klucz1"] = 1,
    ["Klucz2"] = 114,
    ["Klucz3"] = 114,
    ["Klucz5"] = 41
};

Console.WriteLine(data["Klucz1"]);

Alternatywą miało być:

var data = new Dictionary<string, int>()
  {
      $Klucz1 = 1,
      $Klucz2 = 114,
      $Klucz3 = 114,
      $Klucz4 = 41
  };

  Console.WriteLine(data.$Klucz1);

Z tego co wiem jednak, na szczęście nie będzie tego w c# 6.0

Kolejna nowość to inicjalizowanie automatycznych pól. Zawsze irytowało mnie, że samemu musiałem w konstruktorze przypisywać wartości tym właściwościom. Teraz możemy:

class Person
{
  public string FirstName { get; set; }="Piotr";
  public string LastName { get; set; }="Zielinski";
}    

Co prawda sama składnia jest trochę dziwna, ale do zaakceptowania. Nie wiem w sumie jakby to lepiej byłoby zaprojektować (może zwykły atrybut?). W każdym razie nie odstrasza mnie to tak bardzo jak planowany znak $ dla słowników.

Z powyższego wynika również, że można tworzyć właściwości tylko z getterem:

class Person
{
  public string FirstName { get; } ="Piotr";
  public string LastName { get; } = "Zielinski";
}    

Zaglądając do IL, przekonamy się, że nie jest to żadna zmiana w CLR tylko w czystym c# (co nie powinno dziwić):

.class nested private auto ansi beforefieldinit Person
    extends [mscorlib]System.Object
{
    // Fields
    .field private initonly string '<FirstName>k__BackingField'
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
        01 00 00 00
    )
    .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
        01 00 00 00 00 00 00 00
    )
    .field private initonly string '<LastName>k__BackingField'
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
        01 00 00 00
    )
    .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
        01 00 00 00 00 00 00 00
    )

    // Methods
    .method public hidebysig specialname 
        instance string get_FirstName () cil managed 
    {
        .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
            01 00 00 00
        )
        // Method begins at RVA 0x206c
        // Code size 11 (0xb)
        .maxstack 1
        .locals init (
            [0] string
        )

        IL_0000: ldarg.0
        IL_0001: ldfld string ConsoleApplication2.Program/Person::'<FirstName>k__BackingField'
        IL_0006: stloc.0
        IL_0007: br.s IL_0009

        IL_0009: ldloc.0
        IL_000a: ret
    } // end of method Person::get_FirstName

    .method public hidebysig specialname 
        instance string get_LastName () cil managed 
    {
        .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
            01 00 00 00
        )
        // Method begins at RVA 0x2084
        // Code size 11 (0xb)
        .maxstack 1
        .locals init (
            [0] string
        )

        IL_0000: ldarg.0
        IL_0001: ldfld string ConsoleApplication2.Program/Person::'<LastName>k__BackingField'
        IL_0006: stloc.0
        IL_0007: br.s IL_0009

        IL_0009: ldloc.0
        IL_000a: ret
    } // end of method Person::get_LastName

    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x209b
        // Code size 30 (0x1e)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: ldstr "Piotr"
        IL_0006: stfld string ConsoleApplication2.Program/Person::'<FirstName>k__BackingField'
        IL_000b: ldarg.0
        IL_000c: ldstr "Zielinski"
        IL_0011: stfld string ConsoleApplication2.Program/Person::'<LastName>k__BackingField'
        IL_0016: ldarg.0
        IL_0017: call instance void [mscorlib]System.Object::.ctor()
        IL_001c: nop
        IL_001d: ret
    } // end of method Person::.ctor

    // Properties
    .property instance string FirstName()
    {
        .get instance string ConsoleApplication2.Program/Person::get_FirstName()
    }
    .property instance string LastName()
    {
        .get instance string ConsoleApplication2.Program/Person::get_LastName()
    }

} // end of class Person

One thought on “c# 6.0–inicjalizacja słowników oraz automatycznych właściwości”

  1. Właściwości tylko z getterem można też utworzyć po prostu tak:
    class Person
    {
    public string FirstName => “Piotr”;
    public string LastName => “Zielinski”;
    }

Leave a Reply

Your email address will not be published.