C#: Système.Objet vs Génériques
Je vais avoir du mal à comprendre quand utiliser l'Objet (boxing/unboxing) vs quand à l'utilisation des génériques.
Par exemple:
public class Stack
{
int position;
object[] data = new object[10];
public void Push (object o) { data[position++] = o; }
public object Pop() { return data[--position]; }
}
VS.
public class Stack<T>
{
int position;
T[] data = new T[100];
public void Push(T obj) {data[position++] = obj; }
public T Pop() { return data[--position]; }
}
Qui dois-je utiliser et dans quelles conditions? Il semble qu'avec le Système.Objet manière, je peux avoir des objets de toutes sortes de types qui vivent actuellement dans ma Pile. Donc, ne serait-ce pas préférable? Merci!
- Quel est le point d'ajouter un Chat à une collection de Canines? Ce type de flexibilité ne produit que des chats morts.
- Voir cette question liée à une trop why-not-always-use-generics
Vous devez vous connecter pour publier un commentaire.
Toujours utiliser des génériques! À l'aide de l'objet de résultats dans des opérations de transtypage et boxing/unboxing de types de valeur. En raison de ces raisons, les génériques sont plus rapides et plus élégant (pas de conversion). Et la principale raison de ne pas obtenir de
InvalidCastException
s à l'aide de médicaments génériques.Donc, les génériques sont plus rapides et les erreurs sont visibles au moment de la compilation.
System.Object
moyens des exceptions d'exécution et de la coulée qui, en général, des résultats en baisse de rendement (parfois BEAUCOUP moins).Beaucoup de gens ont recommandé l'utilisation de génériques, mais il semble qu'il manque le point. Il n'est souvent pas sur les performances liées à la boxe types de primitives ou de la coulée, il s'agit d'obtenir le compilateur de travailler pour vous.
Si j'ai une liste de chaînes de caractères, je veux le compilateur me prouver qu'il contiendra toujours une liste de chaînes de caractères. Les génériques est juste que - je précise à l'intention, et le compilateur prouve pour moi.
Idéalement, je préfère encore plus riche type de système où l'on peut dire par exemple qu'un type (même si c'est un type de référence) ne pourrait pas contenir de valeurs null, mais le C# n'est malheureusement pas actuellement l'offrir.
Vous presque toujours utiliser des génériques.
L'application du Système.Objet comme un "type" est utilisé:
Noter que dans vous premier échantillon (non générique) l'utilisation ressemble:
Que vous voulez vraiment éviter de tout cela typecasting (pour des raisons de lisibilité, de la sécurité et de la performance).
object
vous obtient à peu près la même chose. Il n'améliore pas la sécurité, mais il n'en est pas pire. Cela signifie également que vous pouvez utiliser LINQ des méthodes directement, sans avoir besoin d'appeler la méthode d'extensionIEnumerable.Cast<object>()
Tandis que il ya des moments où vous souhaitez utiliser un non-générique de la collection (pensez à la mise en cache, par exemple), vous avez presque toujours collections homogènes objets qui ne sont pas objets hétérogènes. Pour un groupe homogène, même si c'est un ensemble de variantes de type de base ou de l'interface, il est toujours préférable d'utiliser des génériques. Cela vous évitera d'avoir à jeter le résultat que le type réel avant de pouvoir l'utiliser. L'utilisation de génériques rend votre code plus efficace et plus lisible, car vous pouvez omettre le code pour faire le casting.
Tout dépend de ce que vous avez besoin dans le long terme.
Contrairement à la plupart des réponses ici, je ne dis pas "toujours utiliser des génériques", parce que parfois vous avez besoin de mélanger les chats avec des concombres.
Par tous les moyens, essayer de coller avec les génériques pour toutes les raisons déjà indiquées dans les autres réponses, par exemple, si vous avez besoin de combiner des chats et des chiens créer de base de la classe des Mammifères et ont
Stack<Mamal>
.Mais quand vous avez vraiment besoin à l'appui de chaque type, n'hésitez pas à utiliser des objets, ils ne mords pas, sauf si vous êtes maltraiter eux. 🙂
Avec le
object
type, comme vous le dites, vous devez effectuer boxing et unboxing, qui est ennuyeux très rapidement. Avec les génériques, il n'y a pas besoin de cela.Aussi, je préfère être plus précis quant à ce genre des objets d'une classe peut travailler avec et génériques fournit une excellente base pour qui. Pourquoi mélanger sans rapport avec les types de données en premier lieu? Votre exemple particulier d'une pile met l'accent sur l'avantage des génériques sur la base
object
type de données.Rappelez-vous que avec les médicaments génériques, vous pouvez spécifier des interfaces de sorte que votre classe peut interagir avec des objets de différentes classes, à condition qu'ils implémentent la même interface.
Utiliser des génériques lorsque vous souhaitez que votre structure pour gérer un seul type. Par exemple, si vous vouliez une collection de chaînes que vous souhaitez instancier un fortement typé Liste de chaînes de caractères comme suit:
Si vous souhaitez gérer plusieurs types que vous pouvez faire sans les génériques, mais vous devrez payer un petit gain de performance pour le boxing/unboxing opérations.
Les génériques sont toujours préférables, si possible.
Côté de la performance, les Génériques de vous permettre de donner des garanties sur les types d'objets que vous travaillez avec.
La principale raison de ce qui est préféré pour le casting, c'est que le compilateur sait quel type de l'objet, et donc peut vous donner des erreurs de compilation que vous trouvez tout de suite au lieu d'exécution des erreurs qui pourraient se produire seulement dans certains scénarios que vous n'avez pas fait de test.
Les génériques ne sont pas marteau d'or. Dans le cas où votre activité est naturellement non générique, utiliser une bonne vieille objet. L'un de ces cas de mise en cache. Cache naturellement peut contenir différents types. J'ai récemment vu cette mise en œuvre de cache wrapper
Question: à quoi bon, si
CacheManager
prend de l'objet?Puis, il y avait vraiment des ravages dans
Get
Le problème ci-dessus est que la valeur de type de panne.
J'ai réparé la méthode par l'ajout de cette
Parce que j'ai comme idée de faire ce
Mais j'ai ajouté de la nouvelle méthode, qui permettra de prendre des types de valeur ainsi
La ligne de fond, il est d'usage pour
object
, en particulier lorsque le stockage des différents types de collecte. Ou lorsque vous avez des compositions où totalement arbitraire et sans rapport avec les objets peuvent exister lorsque vous avez besoin de consommer en fonction de leur type.Parfois vous ne pouvez pas utiliser des génériques pour le but. Par exemple:
Si vous modifiez le paramètre par défaut pour les génériques, il serait une erreur de compilation.