11
votes

.NET: commutateur VS Dictionnaire pour les clés de chaîne

J'ai une situation où j'ai un objet d'affaires avec environ 15 propriétés de différents types. L'objet métier doit également implémenter une interface qui a la méthode suivante:

public bool Field1
{
    get
    {
        return (bool)this.Values["Field1"];
    }
    set
    {
        this.Values["Field1"] = value;
    }
}


8 commentaires

Pourquoi ne pas utiliser de réflexion? Voir ceci Un blog sur la réflexion et les performances Un autre bon article sur la réflexion


Cela ne devrait-il pas être plus lent que l'un de ces deux?


La performance, en milliseconde, est-elle importante?


L'objet sera affiché dans une grille qui interrogera les propriétés. Je vais régulièrement avoir environ 1000 articles dans une telle grille. C'est 15'000 appels de réflexion. Je frémis de penser à ce qui se passerait si chacun d'entre eux a pris 1 ms.


ho, ok c'est assez grand peut-être que la réflexion n'est pas une bonne option dans votre cas


Y a-t-il une raison pour laquelle vous ne liez pas l'objet entier à la grille en tant que datarow?


Pour dire la vérité, c'est la truc de Devexpress Treeelist. C'est comme une TreeView / GridView hybride. Afin que les données doivent être hiérarchiennes. Et l'interface est là pour que le TRÈNE comprend la hiérarchie 'n trucs. Je pourrais probablement aussi traduire tout cela à un jeu de données (il peut aussi se lier à cela), mais c'est plus à l'aise pour moi de travailler avec la suite.


Je veux dire, je ferai également d'autres choses avec cette structure de données plus tard, non seulement l'afficher dans la grille.


4 Réponses :


21
votes
switch:      good efficiency, least maintainable
dictionary:  good efficiency, better maintainability
reflection:  least efficient, best maintainability
Hint: ignore efficiency and worry about maintainability only, unless you've actually tested performance and found it be be an issue.I'm not saying reflection is your only choice, just that it would allow you to add/remove and rename properties as needed, and not need to keep the switch statement or dictionary in sync.

14 commentaires

La réflexion permettrait de découvrir vos propriétés à l'exécution et donc si vous ajoutez / supprimez ou renommez tout, vous n'avez pas besoin de ré-écrire un autre code (tel que l'instruction de commutation ou l'initialisation du dictionnaire).


J'ai tendance à trouver que les frais généraux cognitifs de la réflexion rendent un peu moins à maintenir que l'approche du dictionnaire des tableaux de distribution. Bien que cela puisse être simplement parce que je n'utilise pas très souvent la réflexion. :)


Un dictionnaire plus efficace qu'une déclaration de commutation? Je ne m'attendais pas à cela, pourriez-vous élaborer?


@Papier bulle. Cela pourrait être pour les chaînes. Pour des recherches moins clairsemées, un commutateur sera plus rapide.


@BubbleWrap, je voudrais presque écrire "équivalence égale" pour le commutateur et le dictionnaire, mais je prends simplement une vue générale que l'accès à la mémoire à proximité de O (1) est plus rapide que ce que l'exécution peut faire avec une recherche d'interrupteur. C'est exactement pourquoi je souligne la maintenabilité. Je pourrais changer le libellé de toute façon.


J'ai un peu modifié la question. Pensez toujours que la réflexion est la voie à suivre?


@Greg, bon point. La réflexion n'est pas si difficile, il vous suffit de vous familiariser avec l'arborescence d'objets généralistes et de la navigation autour de cela. Ce que je fais, c'est encapsuler du code de réflexion dans les classes d'attributs d'assistance que vous pouvez ensuite utiliser en ajoutant simplement des atributs à votre code.


@Vilx, comme je suis à l'aise avec la réflexion, je le comparais simplement avec le dictionnaire ou le commutateur (à l'aide de la classe de chronomètre), puis décidez. Oui, 15 000 appels à une version de GetFieldValue () qui utilise une réflexion peut être un problème de performance, mais vous devez le confirmer.


@Vilx, de nombreux cadres d'objet de domaine / affaires telles que CSLA.net vous permettent de "activer / désactiver" la réflexion pour énumérer les propriétés d'objet pour exacylt la situation que vous décrivez (montrant une grille).


Ok, je vais le profiler. C'est vrai - pour la réflexion de maintenance est le moyen le plus simple (je suis à l'aise avec moi aussi). Mais je pense vraiment que cela pourrait facilement manger quelques secondes pendant que la grille s'ouvre. Quelque chose que j'aimerais éviter.


@Vilx, votre approche hybride fonctionnerait en théorie, mais vous avez absolument raison de faire face aux problèmes de maintenabilité supplémentaires qu'il pourrait introduire. J'irais probablement avec le dictionnaire simple ou l'approche de commutation. L'approche hybride commençait à «réinventer la roue» dans cet autre cadre (CSLA) tient une sorte de chose pour vous.


Ma candidature est assez légère et je ne veux pas introduire de cadres orm ou autres. Surtout parce que les données que je vis ne visent pas ne vient pas un format tabulaire soigné à partir d'une SGBDM. Cependant, le dictionnaire hybride ci-dessus devrait être supérieur à un dictionnaire simple dans tous les aspects, y compris la maintenabilité. La déclaration de commutation serait plus simple cependant.


Le commutateur sera généralement le plus rapide et non le dictionnaire (avec peu d'entrées) en fonction de la surcharge de calcul du hashkey, je ne vous fêtait pas de confirmer que la réflexion n'était pas plus rapide que le dictionnaire (sans tester au moins)


@Rune, je peux vous garantir qu'un dictionnaire est plus rapide que l'utilisation de la réflexion. Des hashtables et des dictionnaires en informatique existent car ils peuvent fournir des performances plus élevées pour la récupération des données, puis la plupart des autres structures de données. Considérant que la réflexion existe pour fournir une découverte de types au moment de l'exécution, pas pour des raisons de performance. Mais ne prenez pas ma parole pour cela, essayez une comparaison comme une expérience.



7
votes

Parce que vous utilisez Strings Dictionary sera probablement plus rapide. Le commutateur sera essentiellement traduit par une hache lors de l'utilisation de chaînes. Mais si vous utilisez des INT ou similaires, il est traduit en une table de saut et sera plus rapide.

voir Cette réponse et question pour plus de détails

Meilleur pari est de le profiler et de trouver à coup sûr


0 commentaires

0
votes

Comment vous obtenez la valeur de chaque propriété aura probablement un impact moindre sur la performance globale que la manière dont vous rendez votre grille.

Permettez-moi de vous donner un exemple: Disons que vous avez la mise en œuvre suivante: p>

private string _latestFieldName = string.Empty;
private PropertyInfo _propertyInfo;

object GetFieldValue(string FieldName)
{
  if(FieldName != _latestFieldName)
  {
    _propertyInfo = typeof(yourTypeName).GetProperty(FieldName);
  }
  return _propertyInfo.GetValue(this,null);
}


1 commentaires

NOP, je ne peux pas changer la grille. :)



0
votes

commutateur a réellement 2 avantages comparant au dictionnaire:

  1. Vous pouvez créer un message d'exception personnalisé dans la section par défaut pouvant inclure une valeur non valide. En cas de dictionnaire, vous obtenez uniquement KeyNotFoundException qui ne contenait pas de nom de clé.
  2. Vous pouvez gérer des valeurs null. Dictionnaire ne peut pas stocker NULL comme une clé.

0 commentaires