En passant un IEnumerable de Valeurs Numériques en tant que paramètre à la méthode
Je suis en train de jouer autour avec un programme très simple à prendre un tableau de doubles et de retour de l'écart-type. Cette partie a fonctionné, mais je voulais rendre le code plus réutilisable. Je voudrais faire en sorte que la méthode peut accepter un paramètre de n'importe quel type qui pourrait être considéré numérique et le retour de l'écart-type au lieu de coder en dur une double type (comme je l'ai d'abord fait dans ce programme). Comment fait-on à ce sujet et quel est le bon terme?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
double[] avg = { 3.4, 55.6, 10.0, 4.5, 2, 2 };
double x = avg.Average();
//first round of testing
Console.WriteLine("The average of the first array is below ");
Console.WriteLine(x);
Console.WriteLine("below should be the standard deviation!");
Console.WriteLine(CalculateStandardDeviation(avg));
Console.ReadLine();
int[] intAvg = { 4, 3, 5, 6, 2 };
double secondAvg = intAvg.Average();
Console.WriteLine("The average of the second array is below ");
Console.WriteLine(secondAvg);
//this is where the error is happening
//CalculateStandardDeviation(secondAvg);
}
//this is where I tried to make the query more reusable
public static double CalculateStandardDeviation(IEnumerable<double> values)
{
double avg = values.Average();
double sum = 0;
foreach (double d in values)
{
sum += Math.Pow((d - avg), 2);
}
return Math.Pow(sum / (values.Count() - 1),.5);
}
}
}
Vous pouvez créer une méthode pour chaque type, on peut envisager une validité "d'entrée" et de laisser la surcharge de gérer tous les autres types de peut-être ensuite les jeter à
Vous n'avez pas ce genre de contrainte en C#, il n'y a pas de base
Alors j'ai juste besoin de surcharger la méthode avec tous les possibles de types numériques que je veux inclure?
Ce serait une façon simple de gérer ça, oui. Cependant, ils peuvent tous partagent une même mise en œuvre. Vous n'avez pas à (et ne devrait pas) copier/coller et dupliquer le code dans chaque méthode.
Faites juste attention de la
double
et d'appeler la version qui prend IEnumerable<double>
. Vous pourriez être en mesure de le faire avec les génériques (voir ceci par exemple), mais il n'y a vraiment pas de bonne façon générique limiter aux seuls types numériques.Vous n'avez pas ce genre de contrainte en C#, il n'y a pas de base
Numeric
type. C'est pourquoi, par exemple, Sum
ou Average
ont toutes ces surcharges...Alors j'ai juste besoin de surcharger la méthode avec tous les possibles de types numériques que je veux inclure?
Ce serait une façon simple de gérer ça, oui. Cependant, ils peuvent tous partagent une même mise en œuvre. Vous n'avez pas à (et ne devrait pas) copier/coller et dupliquer le code dans chaque méthode.
Faites juste attention de la
int
surcharge version; vous ne voulez pas utiliser integer division/moyennes (par exemple, 5 / 2 = 2
)OriginalL'auteur wootscootinboogie | 2013-04-16
Vous devez vous connecter pour publier un commentaire.
Vous pouvez utiliser quelque chose comme ceci:
Il va lever une exception si
values
contient des valeurs qui ne peuvent pas être converties en un nombre décimal, mais ne fonctionnera que si les valeurs sont d'un type approprié, et je pense que c'est parfaitement logique.C'est un expression lambda. Lorsque utilisé dans
IEnumerable<T>.Select()
, cela revient à dire "prendre (ce qui est sur la gauche de=>
) et de me donner (ce qui est sur la droite de=>
)".gracias, senor.
Je pense que vous pouvez remplacer
Select(v => Convert.ToDecimal(v))
avecSelect(Convert.ToDecimal)
. Maintenant Wootscootinboogie n'a pas besoin de penser à des expressions lambda 😛C'est une grande idée et cette idée ne l'avait pas traversé l'esprit, mais malheureusement il ne fonctionne pas. Il produit une erreur de compilation: "Pas de surcharge pour le Système.Convertir des.ToDecimal(objet)' correspond à déléguer "Système".Func<T, décimal>'". Vous pourriez faire
values.Cast<object>().Select(Convert.ToDecimal)
, mais je pense que c'est plus complexe que ce qu'il vaut.OriginalL'auteur JLRishe
Malheureusement, il n'y a pas de classe de base pour tous les nombres. Vous pouvez le faire avec un générique au moment de l'exécution de la vérification d'une méthode ou d'un moment de la compilation en sécurité ensemble de surcharges.
Méthode Générique:
Le problème avec l'aide d'une seule méthode générique, c'est que vous ne pouvez pas mettre un type de contrainte sur le paramètre de type de limiter qu'à des types numériques. Vous devez recourir à un défaut au moment de l'exécution. Il n'y aurait rien pour vous empêcher de l'appel de la méthode avec un tableau de chaînes de caractères, ou des objets, ou des Couleurs, ou HttpWebRequests, etc. et à moins que vous ne vous en fait savoir comment calculer l'écart-type d'une couleur, vous devriez probablement s'en tenir à l'individu remplace pour un type numérique:
Je vous conseille d'utiliser le
decimal
type en tant que votre principale la mise en œuvre, puis de casting tout à elle.Spécifiques À Un Type De Surcharges:
Dans .Net 4.5, il fonctionne. Je ne sais pas si ça a toujours été le cas. Je l'ai juste essayé maintenant.
Écart-type de couleurs:
Color.FromArgb(255 - CalculateStandardDeviation(colors.Select(c=>c.A)), CalculateStandardDeviation(colors.Select(c=>c.R)), CalculateStandardDeviation(colors.Select(c=>c.G)), CalculateStandardDeviation(colors.Select(c=>c.B)))
. Des couleurs similaires seront à proximité de noir et opaque.Nice! Maintenant, nous pouvons ajouter une surcharge pour les Couleurs! Ça va être super utile à beaucoup, j'en suis sûr! 🙂
d'accord, mais il y a très peu de types numériques, donc je ne crois pas que, pour être un énorme problème.
OriginalL'auteur Dan
Utiliser Le C# Génériques.
Votre signature de fonction sera:
Et vous pouvez l'utiliser comme:
Veuillez suivre ce lien:
http://msdn.microsoft.com/en-us/library/ms379564%28VS.80%29.aspx
Edit:
Pour résoudre la Moyenne de la question sur les types génériques, veuillez jeter un oeil dans cette bibliothèque:
Comment Implémenter la Méthode Générique pour faire des calculs Mathématiques sur les différents types de valeur
Obs: Suggestion de Brian.
Comment voulez-vous faire la soustraction et la
Average
sur le type deT
?Je downvoted la réponse parce que c'est incorrect. Il n'y a aucun moyen de mettre en œuvre la méthode de la signature, et non pas comme il est d'aider les OP à résoudre leur problème. J'ai toujours supprimer un downvote si elle n'est plus justifiée.
Mon point était de présenter les Génériques concept et de la hausse de l'utilisateur criativity de l'avant ainsi conçu une solution. Merci @NickFreeman, je suis d'accord avec vous.
Honnêtement, je pense que la diligence raisonnable serait un exemple, le travail de mise en œuvre, car il est un peu difficile de savoir comment cela fonctionne réellement. Mais j'ai enlevé mon downvote.
OriginalL'auteur gustavodidomenico
MODIFIER
Vous devez utiliser JLRishe de réponse, il est beaucoup plus élégant que cette.
Vous devriez probablement commencer par l'ajout de médicaments génériques à votre méthode et utiliser le type de convertisseur pour transformer votre inconnu d'entrée en double comme suit :
Je n'ai pas testé cet extrait, mais vous obtenez l'idée.
OriginalL'auteur gxtaillon
Avant-propos:
cette réponse s'appuie sur
Comment vérifier si un type de surcharges/prise en charge d'un certain opérateur?
et
http://www.codeproject.com/Articles/87438/TinyLisp-A-Language-and-Parser-to-See-LINQ-Express
Le second lien montre comment compiler et d'évaluer des expressions linq.
En bref, on pourrait renoncer type statique de la sécurité et de vérifier la capacité d'un type à l'appui des opérations spécifiques au moment de l'exécution (premier lien), dans le cas où il ne fait pas de vous pourrait jeter une exception, comme l'exemple suivant le démontre:
Merci pour vos commentaires, il est apprécié.
OriginalL'auteur Andrea Scarcella
Passage d'un IEnumerable de Valeurs Numériques en tant que paramètre à la méthode sera pris en charge en C# 6.0
OriginalL'auteur Will Yu