53 votes

Pourquoi devrais-je faire en sorte que le type sous-jacent d'un Enum soit Int32 au lieu d'octet ?

Étant donné l'énumération suivante :

public enum Operations_PerHourType : byte
{
    Holes = 1,
    Pieces = 2,
    Sheets = 3,
    Strips = 4,
    Studs = 5
}

Quand je lance l'outil d'analyse de code de Microsoft, il me dit :

CA1028 : Microsoft.Design : Si possible, faites en sorte que le type sous-jacent de 'Enums.Operations_PerHourType' soit System.Int32 au lieu de 'byte'.

Il n'aura jamais plus de deux valeurs possibles, donc je l'ai déclaré comme un octet. Pourquoi recommanderaient-ils d'utiliser int32 ? Plus de valeurs pour l'évolutivité future ? Ou y a-t-il une amélioration des performances ?

40voto

Jason Down Points 13690

Jetez un coup d'œil sur MSDN pour la raison.

En voici un extrait :

Une énumération est un type de valeur qui définit un ensemble de valeurs apparentées nommées constantes nommées. Par défaut, le type de données System.Int32 est utilisé pour stocker la valeur de la constante. Même si vous pouvez modifier ce type sous-jacent, il n'est pas nécessaire ou recommandé dans la plupart des scénarios. Notez qu'aucun gain de performance significatif n'est obtenu en utilisant un type de données qui est plus petit que Int32. Si vous ne pouvez pas utiliser le type de données par défaut, vous vous devez utiliser l'un des types intégraux compatibles avec le Common Language System (CLS) Byte, Int16, Int32 ou Int64, afin de vous assurer que toutes les valeurs de l'énumération l'énumération puissent être représentées dans un langage de programmation conforme au CLS de programmation conformes au CLS.

24voto

Jirka Hanika Points 8266

Il existe des situations spécifiques où le fait de restreindre le type sous-jacent apporte certains avantages, par exemple en matière de performances ou pour forcer une disposition particulière de la mémoire lors de l'interfaçage avec du code non géré.

Considérez cet échantillon :

using System;

public enum Operations_PerHourType //   : byte
{
    Holes = 1,
    Pieces = 2,
    Sheets = 3,
    Strips = 4,
    Studs = 5
}

class Program
{
    static void Main()
    {
        long before = GC.GetTotalMemory(false);
        var enums = new Operations_PerHourType[10000];
        long after = GC.GetTotalMemory(false);

        Console.WriteLine(after - before);
        // output  (byte): 12218 (I'm using Mono 2.8)
        // output (Int32): 40960
    }
}

Ce code consomme environ 40 Ko du tas. Maintenant, spécifiez (dé-commentez) le type sous-jacent en tant que byte et recompiler. Wow. Tout à coup, nous n'avons plus besoin que d'environ 10 Ko.

Compacter la mémoire de cette manière peut parfois rendre un programme plus lent, et non plus rapide, selon les modèles d'accès et les tailles de données. Il n'y a pas d'autre moyen d'en être sûr que de faire quelques mesures et d'essayer de généraliser à d'autres circonstances possibles. La traversée séquentielle de données plus petites est généralement plus rapide.

Cependant, prendre l'habitude de spécifier des types étroits simplement parce que c'est généralement possible et parfois crucial, n'est pas une bonne idée. Les économies de mémoire se matérialisent rarement en raison de l'alignement mémoire des types de données plus larges environnants. Les performances sont alors soit identiques, soit légèrement inférieures en raison des instructions supplémentaires nécessaires pour masquer les octets de remplissage.

Comme une autre réponse l'a déjà bien exprimé, suivez les Int32 Il s'agit d'une foule de personnes pour lesquelles le moteur d'exécution est optimisé, jusqu'à ce que vous deviez commencer à profiler et à traiter les véritables problèmes de mémoire dans votre application.

21voto

Kevin Points 57797

Selon la documentation, il n'y a pas de gain de performance à utiliser un octet au lieu d'INT32. À moins qu'il y ait une raison de le faire, ils recommandent de ne pas le changer. L'idée sous-jacente est que .NET est optimisé pour l'utilisation d'INT32 dans de nombreux scénarios, et qu'ils l'ont choisi pour les enums pour une raison précise. Vous n'obtenez rien dans votre scénario en le changeant, alors pourquoi s'en préoccuper.

http://msdn.microsoft.com/en-us/library/ms182147.aspx

Il explique également comment .NET est optimisé pour utiliser des entiers de 32 bits : Int32 optimisé pour .NET

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X