Utilise pour la statique des classes génériques?
Quelles sont les principales utilisations d'un Statique Classe Générique en C#? Quand doivent-elles être utilisées? Quels exemples illustrent au mieux leur utilisation?
par exemple
public static class Example<T>
{
public static ...
}
Puisque vous ne pouvez pas définir les méthodes d'extension en eux, ils semblent être quelque peu limités dans leur utilité. Références Web sur le sujet sont rares, donc clairement il n'y a pas beaucoup de gens de les utiliser. Voici un couple:-
http://ayende.com/Blog/archive/2005/10/05/StaticGenericClass.aspx
Statique de la Classe Générique comme Dictionnaire
Résumé des Réponses données
Les questions clés semblent être "Quelle est la différence entre un statique de la classe générique avec des méthodes statiques et un non générique classe statique statique générique membres?"
La décision quant à l'utilisation semble tourner autour de "le besoin de classe pour le type de magasin d'état spécifique en interne?"
Si il n'est pas nécessaire pour le type spécifique de stockage interne puis une statique non-classe générique générique de méthodes statiques semble préférable, car la syntaxe d'appel est plus agréable et vous pouvez définir des méthodes d'extension à l'intérieur.
Vous devez vous connecter pour publier un commentaire.
Je utiliser des classes génériques pour la mise en cache de la réflexion lourde de code.
Disons que j'ai besoin de construire une arborescence d'expression qui instancie les objets. Je construis une fois dans le constructeur statique de la classe, le compiler pour une expression lambda, puis de les mettre en cache un membre de la classe statique. Souvent, je ne fais pas ces classes publiquement évaluables - ils sont généralement les aides pour les autres classes. Par la mise en cache mes expressions de cette façon, j'évite la nécessité de cache mes expressions dans une sorte de
Dictionary<Type, delegate>
.Il est un exemple de ce motif dans la BCL. L' (
DataRow
) les méthodes d'extensionField<T>()
etSetField<T>()
utiliser le (privé) statique de la classe génériqueSystem.Data.DataRowExtensions+UnboxT<T>
. Check it out avec Réflecteur.Rendre une classe
static
ne pas ajouter de fonctionnalité, il est juste un moyen pratique de vérifier si vous avez l'intention d'utiliser une classe sans instanciation. Et il y a plusieurs utilisations pour ça...Vous pouvez utiliser des classes génériques pour contourner une limitation: C# n'a pas permis partielle de la spécialisation. Cela signifie que vous devez spécifier tous les paramètres de type ou aucun. Cependant, qui peut être inutilement verbeux.
Par exemple:
la classe précédente n'a pas permis de l'inférence de type depuis l'inférence ne fonctionne pas sur les valeurs de retour. Cependant, vous ne pouvez pas indiquer la valeur de retour de type sans préciser le type d'entrée puisque vous ne pouvez pas partiellement se spécialiser. À l'aide d'un (peut-être statique) classe générique, vous pouvez spécifier qu'un seul des deux types:
De cette façon, vous pouvez laisser l'inférence de type travail sur le type de paramètre et ne spécifier que le type de retour.
(Bien que le cas ci-dessus est concevable, il ne nécessite pas la classe générique à être statique, bien sûr).
Deuxièmement, (comme Steven tout d'abord souligné) séparé champs statiques existe pour chaque type construit, et qui rend les classes statiques d'excellents endroits pour stocker des informations supplémentaires sur les types ou combinaisons de type de. En essence, c'est un semi-statique de la table de hachage que les touches sur les types.
Un semi-statique de la table de masquage sur les types de sons un peu arcance, mais il est en fait très, très utile la structure, car il vous permet de stocker cher de réflexion et de génération de code où ils sont presque gratuites à regarder en haut (moins cher qu'un dictionnaire, parce que ça devient JIT-ed et de vous éviter un appel à
.GetType()
). Si vous êtes en train de faire la métaprogrammation, c'est génial!Par exemple, je l'utilise dans ValueUtils pour stocker généré fonctions de hachage:
Statique méthodes génériques permettent l'inférence de type pour que l'utilisation vraiment facile; les champs statiques sur les classes génériques permettant à presque frais-gratuit de stockage de (méta)données. Il ne m'étonne pas du tout si l'ORM est comme Dapper et PetaPoco utiliser des techniques comme cela; mais il est également grand pour (de)sérialiseurs. Une limitation est que vous obtenez le faible temps parce que vous êtes la liaison à la au moment de la compilation type; si l'objet qui est passé est en fait une instance d'une sous-classe, vous êtes probablement de liaison pour le mauvais type et l'ajout de vérifications pour éviter ce genre de sape de l'avantage d'une faible surcharge.
Champs statiques d'un type générique sont spécifiques au type réel T. Cela signifie que vous pouvez stocker un type spécifique de cache interne. Cela pourrait être une raison pour créer un statique de type générique. Voici une (plutôt inutile, mais informative) exemple:
T
.instance
de typeT
?Une utilisation de la statique des classes génériques que j'ai récemment appris a été possible de définir une contrainte sur le niveau de la classe pour le type, la contrainte s'applique à tous les membres statiques de la classe, ce que j'ai également appris, c'est que ce n'est pas autorisé pour la statique des classes génériques qui définissent l'extension des méthodes.
Par exemple, si vous allez créer un statique de la classe générique et vous savez tous les types génériques devraient être IComparable (juste un exemple), alors vous pouvez effectuer les opérations suivantes.
Avis que je n'ai pas besoin d'appliquer la contrainte à tous les membres, mais juste au niveau de la classe.
Le premier blog que vous mentionnez montre une utilisation valide (comme un référentiel statique de la classe pour une ActiveRecord mise en œuvre):
Ou si vous voulez mettre en œuvre différentes méthodes de tri pour les tableaux:
Je pense en général, vous devriez éviter de créer des paramètres de type statique, classes, sinon vous pouvez dépend pas de l'inférence de type pour faire de votre client code plus concis.
Pour donner un exemple concret, imaginons que vous êtes en train de rédiger un statique de la classe utilitaire pour gérer les opérations sur les Listes. Vous pouvez écrire la classe de deux façons:
Mais les classes sont équivalentes, mais qui est facile à utiliser? Comparer:
À mon avis,
ListOps<someType>
est encombrant et maladroit. La définition de la vanille classe est légèrement plus grande, mais le code du client est plus facile à lire -- grâce à l'inférence de type.Dans le pire des cas, C# ne pouvez pas déduire les types, et vous devez les spécifier à la main. Préférez-vous écrire
ListOps<A>.Map<B>(...)
ouListOps.Map<A, B>(...)
? Ma préférence va vers le dernier.La stratégie ci-dessus fonctionne particulièrement bien lorsque votre classe statique détient pas mutable état, ou de ses mutable état est connu au moment de la compilation.
Si la classe statique détient mutable état dont le type n'est pas déterminé au moment de la compilation, alors vous avez probablement un cas d'utilisation pour une classe statique avec générique params. Espérons que ces occasions sont rares et loin entre, mais quand il arrive, vous serez heureux C# prend en charge la fonctionnalité.
Je les utiliser pour simuler une DbSet lors de l'essai contre les classes qui utilisent EntityFramework méthodes Asynchrones.
Et de les utiliser comme dans mes tests unitaires - permet d'économiser beaucoup de temps et peut les utiliser pour tout les types d'entité:
Vous avez raison: ils ne sont pas beaucoup d'utilisation. Peut-être il y a quelques rares cas qui sont des exceptions, cependant. Par exemple, si la classe est un type de dépôt, comme pour Justin exemple, mais a gardé une statique de la collection comme un cache? En général, si elle contient de l'état, non seulement les méthodes, il y a peut-être un point à ce.
Une statique de la classe générique est exactement comme utile que n'importe quelle donnée statique de la classe. La différence est que vous n'avez pas à utiliser le copier-coller pour créer une version de la classe statique pour chaque type que vous voulez qu'il fonctionne sur. Vous faites de la classe générique, et vous pouvez "générer" une version pour chaque ensemble de paramètres de type.