Code Review: Publiczny enum

Załóżmy, że w kodzie zobaczymy enum’a np.:

public enum Colors
{
   Black,
   Red,
   Yellow
};

Jeśli budujemy framework lub jakąkolwiek bibliotekę należy być świadomym zagrożeń wynikających z wewnętrznej budowy enum’a. Warto zajrzeć do Reflector’a aby przekonać się o tym:

.class public auto ansi sealed Colors
    extends [mscorlib]System.Enum
{
    .field public static literal valuetype ConsoleApplication1.Colors Black = int32(0)

    .field public static literal valuetype ConsoleApplication1.Colors Red = int32(1)

    .field public specialname rtspecialname int32 value__

    .field public static literal valuetype ConsoleApplication1.Colors Yellow = int32(2)

}

Problemem są oczywiście stałe. Powyższy enum wygląda mniej więcej następująco:

public static class CustomColors
{
   public const int Black = 0;
   public const int Red = 1;
   public const int Yellow = 2;
}

Jeśli ktoś nie kojarzy problemów ze stałymi to zapraszam do mojego wpisu tutaj. W skrócie, stała jest wstrzykiwana na etapie kompilacji. Po kompilacji, miejsce gdzie odwołujemy się do stałej jest zastępowane konkretną wartością. Jeśli piszemy system modularny wtedy w końcu możliwe jest, że biblioteka ze stałymi zostanie zmodyfikowana. Niestety wszystkie zależne biblioteki nie będą odzwierciedlać tej zmiany bez ponownej kompilacji. Oczywiście jeśli stała jest faktycznie niezmienna (klasyczny przykład PI) wtedy nie ma z tym problemu. Dobrą praktyką jednak jest (jeśli nie ma się do tego pewności) użycie pól read-only zamiast const, jeśli musimy zadeklarować dane pole jako publiczne. Każdy element publiczny powinien być zaprojektowany w ten sposób, że nie wymaga rekompilacji – w końcu udostępniamy go innym programistom.

Jeśli powyższe ryzyka faktycznie są nie do zaakceptowania dla danego projektu, wtedy po prostu lepiej napisać:

public static class CustomColors
{
   public static readonly int Black = 0;
   public static readonly int Red = 1;
   public static readonly int Yellow = 2;
}

Zostanie to przetłumaczone na:

.class public abstract auto ansi sealed beforefieldinit CustomColors
    extends [mscorlib]System.Object
{
    .method private hidebysig specialname rtspecialname static void .cctor() cil managed
    {
    }


    .field public static initonly int32 Black

    .field public static initonly int32 Red

    .field public static initonly int32 Yellow

}

 

Leave a Reply

Your email address will not be published.