Bonjour,
Je me demande ce qui est le mieux dans le cas suivant: j'ai une variable
ArrayList qui va être traité par différentes fonctions
(ajout/suppression de membres, modification de membres):
Il manque le cas C (héritage): class MyArrayList : ArrayList
{
public void Modify() {/*...*/}
}
MyArrayList myList = new MyArrayList();
myList.Modify();
cdlt, Frédéric.
"julien" wrote in message news:421ba3b0$0$14786$
Bonjour, Je me demande ce qui est le mieux dans le cas suivant: j'ai une variable ArrayList qui va être traité par différentes fonctions (ajout/suppression de membres, modification de membres):
cas B: ArrayList list = modifyB1(); list = modifyB2(list); list = modifyB3(list); list = modifyB4(list);
Merci Julien
Bonsoir,
Il manque le cas C (héritage):
class MyArrayList : ArrayList
{
public void Modify() {/*...*/}
}
MyArrayList myList = new MyArrayList();
myList.Modify();
cdlt,
Frédéric.
"julien" <julien@sobrier.net> wrote in message
news:421ba3b0$0$14786$636a15ce@news.free.fr...
Bonjour,
Je me demande ce qui est le mieux dans le cas suivant: j'ai une variable
ArrayList qui va être traité par différentes fonctions (ajout/suppression
de membres, modification de membres):
Il manque le cas C (héritage): class MyArrayList : ArrayList
{
public void Modify() {/*...*/}
}
MyArrayList myList = new MyArrayList();
myList.Modify();
cdlt, Frédéric.
"julien" wrote in message news:421ba3b0$0$14786$
Bonjour, Je me demande ce qui est le mieux dans le cas suivant: j'ai une variable ArrayList qui va être traité par différentes fonctions (ajout/suppression de membres, modification de membres):
cas B: ArrayList list = modifyB1(); list = modifyB2(list); list = modifyB3(list); list = modifyB4(list);
Merci Julien
Sylvain Lafontaine
Meilleur dans quel sens? vitesse, empreinte mémoire, nombre de touches à taper au clavier?
Personnellement, je vous suggèrerais le cas A car il vous permet d'utiliser la valeur de retour d'une fonction pour autre chose, comme par exemple retourner un message d'erreur ou le nombre de lignes affectées.
Évidemment et tel que suggéré dans un des posts précédents, l'héritage ou l'inclusion dans une classe est peut-être une solution encore meilleure.
S. L.
"julien" wrote in message news:421ba3b0$0$14786$
Bonjour, Je me demande ce qui est le mieux dans le cas suivant: j'ai une variable ArrayList qui va être traité par différentes fonctions (ajout/suppression de membres, modification de membres):
cas B: ArrayList list = modifyB1(); list = modifyB2(list); list = modifyB3(list); list = modifyB4(list);
Merci Julien
Meilleur dans quel sens? vitesse, empreinte mémoire, nombre de touches à
taper au clavier?
Personnellement, je vous suggèrerais le cas A car il vous permet d'utiliser
la valeur de retour d'une fonction pour autre chose, comme par exemple
retourner un message d'erreur ou le nombre de lignes affectées.
Évidemment et tel que suggéré dans un des posts précédents, l'héritage ou
l'inclusion dans une classe est peut-être une solution encore meilleure.
S. L.
"julien" <julien@sobrier.net> wrote in message
news:421ba3b0$0$14786$636a15ce@news.free.fr...
Bonjour,
Je me demande ce qui est le mieux dans le cas suivant: j'ai une variable
ArrayList qui va être traité par différentes fonctions (ajout/suppression
de membres, modification de membres):
Meilleur dans quel sens? vitesse, empreinte mémoire, nombre de touches à taper au clavier?
Personnellement, je vous suggèrerais le cas A car il vous permet d'utiliser la valeur de retour d'une fonction pour autre chose, comme par exemple retourner un message d'erreur ou le nombre de lignes affectées.
Évidemment et tel que suggéré dans un des posts précédents, l'héritage ou l'inclusion dans une classe est peut-être une solution encore meilleure.
S. L.
"julien" wrote in message news:421ba3b0$0$14786$
Bonjour, Je me demande ce qui est le mieux dans le cas suivant: j'ai une variable ArrayList qui va être traité par différentes fonctions (ajout/suppression de membres, modification de membres):
cas B: ArrayList list = modifyB1(); list = modifyB2(list); list = modifyB3(list); list = modifyB4(list);
Merci Julien
Remi Thomas - MVP
"julien" écrivit
Bonjour, Je me demande ce qui est le mieux dans le cas suivant: j'ai une variable ArrayList qui va être traité par différentes fonctions (ajout/suppression de membres, modification de membres):
Bonjour,
Pour ton utilisation il faut utiliser le cas B. Pas besoin de passer par référence. En .NET tout objet crée avec un new est un pointeur. Donc tu ne passes que le pointeur de ton arraylist.
Rémi
-- Rémi Thomas - MVP Visual Studio .NET Développeur Windows indépendant http://www.xtware.com/cv
"julien" écrivit
Bonjour,
Je me demande ce qui est le mieux dans le cas suivant: j'ai une variable
ArrayList qui va être traité par différentes fonctions (ajout/suppression
de membres, modification de membres):
Bonjour,
Pour ton utilisation il faut utiliser le cas B.
Pas besoin de passer par référence.
En .NET tout objet crée avec un new est un pointeur. Donc tu ne passes que
le pointeur de ton arraylist.
Rémi
--
Rémi Thomas - MVP Visual Studio .NET
Développeur Windows indépendant
http://www.xtware.com/cv
Bonjour, Je me demande ce qui est le mieux dans le cas suivant: j'ai une variable ArrayList qui va être traité par différentes fonctions (ajout/suppression de membres, modification de membres):
Bonjour,
Pour ton utilisation il faut utiliser le cas B. Pas besoin de passer par référence. En .NET tout objet crée avec un new est un pointeur. Donc tu ne passes que le pointeur de ton arraylist.
Rémi
-- Rémi Thomas - MVP Visual Studio .NET Développeur Windows indépendant http://www.xtware.com/cv
Zazar
julien a écrit :
Bonjour, Je me demande ce qui est le mieux dans le cas suivant: j'ai une variabl e ArrayList qui va être traité par différentes fonctions (ajout/suppression de membres, modification de membres):
cas B: ArrayList list = modifyB1(); list = modifyB2(list); list = modifyB3(list); list = modifyB4(list);
C'est de la gymnastique pour rien.
Cas C proposé par Frédéric Queudret : > Il manque le cas C (héritage): > class MyArrayList : ArrayList > > { > > public void Modify() {/*...*/} > > }
Ca dépend de ce que font les fonctions modify, de si l'objet est réutilisé ailleurs, ... Je dirais que ça peut être la meilleure m éthode comme la pire selon le contexte.
-- Zazar
julien a écrit :
Bonjour,
Je me demande ce qui est le mieux dans le cas suivant: j'ai une variabl e
ArrayList qui va être traité par différentes fonctions
(ajout/suppression de membres, modification de membres):
cas B:
ArrayList list = modifyB1();
list = modifyB2(list);
list = modifyB3(list);
list = modifyB4(list);
C'est de la gymnastique pour rien.
Cas C proposé par Frédéric Queudret :
> Il manque le cas C (héritage):
> class MyArrayList : ArrayList
>
> {
>
> public void Modify() {/*...*/}
>
> }
Ca dépend de ce que font les fonctions modify, de si l'objet est
réutilisé ailleurs, ... Je dirais que ça peut être la meilleure m éthode
comme la pire selon le contexte.
Bonjour, Je me demande ce qui est le mieux dans le cas suivant: j'ai une variabl e ArrayList qui va être traité par différentes fonctions (ajout/suppression de membres, modification de membres):
cas B: ArrayList list = modifyB1(); list = modifyB2(list); list = modifyB3(list); list = modifyB4(list);
C'est de la gymnastique pour rien.
Cas C proposé par Frédéric Queudret : > Il manque le cas C (héritage): > class MyArrayList : ArrayList > > { > > public void Modify() {/*...*/} > > }
Ca dépend de ce que font les fonctions modify, de si l'objet est réutilisé ailleurs, ... Je dirais que ça peut être la meilleure m éthode comme la pire selon le contexte.
-- Zazar
Ambassadeur Kosh
> Dans le cas général, le mieux est :
on peut aller encore plus loin. "tu ne feras pas de side effect sur un parametre" conduit à :
public class ArrayWorker { public ArrayWorker(ArrayList list) ;
public void modifyA1() ; public void modifyA2() ; public void modifyA3() ; }
mais bon... par contre, il y'a aussi un principe qui dit "une fonction ne fait pas de side object sur l'objet, pour une methode, si, et c'est même son but"
public class Circle { private double x ; private double y ;
// pas touche à x et y public double Area() ;
// modifie x et y public void Translate(double dx,double dy) ; }
faire preuve de pragmatisme, et regarder le framework permettront surement de se faire un bagage valable. bon courage
> Dans le cas général, le mieux est :
on peut aller encore plus loin. "tu ne feras pas de side effect sur un
parametre" conduit à :
public class ArrayWorker
{
public ArrayWorker(ArrayList list) ;
public void modifyA1() ;
public void modifyA2() ;
public void modifyA3() ;
}
mais bon...
par contre, il y'a aussi un principe qui dit "une fonction ne fait pas de
side object sur l'objet, pour une methode, si, et c'est même son but"
public class Circle
{
private double x ;
private double y ;
// pas touche à x et y
public double Area() ;
// modifie x et y
public void Translate(double dx,double dy) ;
}
faire preuve de pragmatisme, et regarder le framework permettront surement
de se faire un bagage valable.
bon courage
on peut aller encore plus loin. "tu ne feras pas de side effect sur un parametre" conduit à :
public class ArrayWorker { public ArrayWorker(ArrayList list) ;
public void modifyA1() ; public void modifyA2() ; public void modifyA3() ; }
mais bon... par contre, il y'a aussi un principe qui dit "une fonction ne fait pas de side object sur l'objet, pour une methode, si, et c'est même son but"
public class Circle { private double x ; private double y ;
// pas touche à x et y public double Area() ;
// modifie x et y public void Translate(double dx,double dy) ; }
faire preuve de pragmatisme, et regarder le framework permettront surement de se faire un bagage valable. bon courage
Zazar
Bonjour,
on peut aller encore plus loin. "tu ne feras pas de side effect sur un parametre" conduit à :
public class ArrayWorker { public ArrayWorker(ArrayList list) ;
public void modifyA1() ; public void modifyA2() ; public void modifyA3() ; }
Effectivement, mais dans ce cas là, il faut aussi faire un clone dans l e constructeur et prévoir une fonction GetResult().
mais bon... par contre, il y'a aussi un principe qui dit "une fonction ne fait pas de side object sur l'objet, pour une methode, si, et c'est même son but"
Je ne comprends pas le "par contre" : il y a une contradiction entre ce principe et le code ci-dessus qui m'échappe ?
<HS> Sinon, suite à notre dernière discussion, vous ne m'avez pas dit ce q ue vous pensiez de l'utilisation des DynamicMethod couplées aux generics ? </HS>
-- Zazar
Bonjour,
on peut aller encore plus loin. "tu ne feras pas de side effect sur un
parametre" conduit à :
public class ArrayWorker
{
public ArrayWorker(ArrayList list) ;
public void modifyA1() ;
public void modifyA2() ;
public void modifyA3() ;
}
Effectivement, mais dans ce cas là, il faut aussi faire un clone dans l e
constructeur et prévoir une fonction GetResult().
mais bon...
par contre, il y'a aussi un principe qui dit "une fonction ne fait pas de
side object sur l'objet, pour une methode, si, et c'est même son but"
Je ne comprends pas le "par contre" : il y a une contradiction entre ce
principe et le code ci-dessus qui m'échappe ?
<HS>
Sinon, suite à notre dernière discussion, vous ne m'avez pas dit ce q ue
vous pensiez de l'utilisation des DynamicMethod couplées aux generics ?
</HS>
on peut aller encore plus loin. "tu ne feras pas de side effect sur un parametre" conduit à :
public class ArrayWorker { public ArrayWorker(ArrayList list) ;
public void modifyA1() ; public void modifyA2() ; public void modifyA3() ; }
Effectivement, mais dans ce cas là, il faut aussi faire un clone dans l e constructeur et prévoir une fonction GetResult().
mais bon... par contre, il y'a aussi un principe qui dit "une fonction ne fait pas de side object sur l'objet, pour une methode, si, et c'est même son but"
Je ne comprends pas le "par contre" : il y a une contradiction entre ce principe et le code ci-dessus qui m'échappe ?
<HS> Sinon, suite à notre dernière discussion, vous ne m'avez pas dit ce q ue vous pensiez de l'utilisation des DynamicMethod couplées aux generics ? </HS>
-- Zazar
julien
Zazar wrote:
julien a écrit :
Bonjour, Je me demande ce qui est le mieux dans le cas suivant: j'ai une variable ArrayList qui va être traité par différentes fonctions (ajout/suppression de membres, modification de membres):
ArrayList est un type référence : pas besoin d'utiliser ref.
Et la définition de modiyA1 doit être void modifyA1(ref ArrayList list) ou modifyA1(ArrayList list)?
Merci Julien
Zazar wrote:
julien a écrit :
Bonjour,
Je me demande ce qui est le mieux dans le cas suivant: j'ai une
variable ArrayList qui va être traité par différentes fonctions
(ajout/suppression de membres, modification de membres):
Bonjour, Je me demande ce qui est le mieux dans le cas suivant: j'ai une variable ArrayList qui va être traité par différentes fonctions (ajout/suppression de membres, modification de membres):
ArrayList est un type référence : pas besoin d'utiliser ref.
Et la définition de modiyA1 doit être void modifyA1(ref ArrayList list) ou modifyA1(ArrayList list)?
Merci Julien
Zazar
Bonjour,
Et la définition de modiyA1 doit être void modifyA1(ref ArrayList l ist) ou modifyA1(ArrayList list)?
Ca doit être la seconde, la première ne compilera même pas. Vous de vriez jeter un oeil sur la documentation des mots-clef ref et out pour voir exactement à quoi ils servent.
-- Zazar
Bonjour,
Et la définition de modiyA1 doit être void modifyA1(ref ArrayList l ist)
ou modifyA1(ArrayList list)?
Ca doit être la seconde, la première ne compilera même pas. Vous de vriez
jeter un oeil sur la documentation des mots-clef ref et out pour voir
exactement à quoi ils servent.
Et la définition de modiyA1 doit être void modifyA1(ref ArrayList l ist) ou modifyA1(ArrayList list)?
Ca doit être la seconde, la première ne compilera même pas. Vous de vriez jeter un oeil sur la documentation des mots-clef ref et out pour voir exactement à quoi ils servent.
-- Zazar
Ambassadeur Kosh
> Je ne comprends pas le "par contre" : il y a une contradiction entre ce principe et le code ci-dessus qui m'échappe ?
c'est dans le "niveau de contestabilité". maintenant, c'est un jugement de valeur. ça reste subjectif, et personel.
Sinon, suite à notre dernière discussion, vous ne m'avez pas dit ce que vous pensiez de l'utilisation des DynamicMethod couplées aux generics ?
et bien, c'est trés idiot, mais je n'ai pas exactement compris ou m'en servir une fois que je me suis lancé dans le truc. d'autre part, ma petite enquete m'a amené à penser que si j'ai besoin de perfs, je privilegierai la generation de code et la specialisation. mais pour l'instant, le cout de la genericité est negligeable dans la balance. ce qui prime est la compilation et le typage "fort".
par exemple, dans le source qui suit, entre le top et le bottom, horsmis des cas surréalistes de clients qui piquent une crise pour 10 secondes de plus sur 3 minutes d'execution, je choisirai d'implanter le top.
public delegate T BinaryFunction<T>(T x,T y) ;
public abstract class BinaryOperator<T> { protected BinaryOperator() { }
public abstract T Compute(T x,T y) ; }
public static class PlusFunction { public static decimal Decimal(decimal x, decimal y) { return x + y; } public static double Double(double x, double y) { return x + y; } public static float Single(float x, float y) { return x + y; } }
public static class PlusOperator { public static readonly BinaryOperator<decimal> Decimal = new DecimalPlus(); public static readonly BinaryOperator<double> Double = new DoublePlus(); public static readonly BinaryOperator<float> Single = new SinglePlus();
private class DecimalPlus : BinaryOperator<decimal> { public override decimal Compute(decimal x, decimal y) { return x + y; } } private class DoublePlus : BinaryOperator<double> { public override double Compute(double x, double y) { return x + y; } } private class SinglePlus : BinaryOperator<float> { public override float Compute(float x, float y) { return x + y; } } }
public static class Stl { // 0 : specialisation v public static T Accumulate1<T>(IEnumerable<T> v, BinaryFunction<T> function, T zero) { T result = zero;
foreach (T x in v) result = function(result, x);
return result; } public static T Accumulate0<T>(IList<T> v, BinaryFunction<T> function, T zero) { T result = zero;
foreach (T x in v) result = function(result, x);
return result; } public static T Accumulate2<T>(T[] v, BinaryFunction<T> function, T zero) { T result = zero;
foreach (T x in v) result = function(result, x);
return result; }
// 1 : T -> decimal public static decimal Accumulate1d(IEnumerable<decimal> v, BinaryFunction<decimal> function, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = function(result, x);
return result; } public static decimal Accumulate0d(IList<decimal> v, BinaryFunction<decimal> function, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = function(result, x);
return result; } public static decimal Accumulate2d(decimal[] v, BinaryFunction<decimal> function, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = function(result, x);
return result; }
// 2 : function = delegate | class public static T Accumulate1o<T>(IEnumerable<T> v, BinaryOperator<T> function, T zero) { T result = zero;
foreach (T x in v) result = function.Compute(result, x);
return result; } public static T Accumulate0o<T>(IList<T> v, BinaryOperator<T> function, T zero) { T result = zero;
foreach (T x in v) result = function.Compute(result, x);
return result; } public static T Accumulate2o<T>(T[] v, BinaryOperator<T> function, T zero) { T result = zero;
foreach (T x in v) result = function.Compute(result, x);
return result; } public static decimal Accumulate1do(IEnumerable<decimal> v, BinaryOperator<decimal> function, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = function.Compute(result, x);
return result; } public static decimal Accumulate0do(IList<decimal> v, BinaryOperator<decimal> function, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = function.Compute(result, x);
return result; } public static decimal Accumulate2do(decimal[] v, BinaryOperator<decimal> function, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = function.Compute(result, x);
return result; }
// non traité : BinaryOperator<decimal> -> DecimalPlus
// 3 : inlining plus |- ?di = ?doi public static decimal Accumulate1doi(IEnumerable<decimal> v, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = result + x;
return result; } public static decimal Accumulate0doi(IList<decimal> v, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = result + x ;
return result; } public static decimal Accumulate2doi(decimal[] v, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = result + x ;
return result; } }
> Je ne comprends pas le "par contre" : il y a une contradiction entre ce
principe et le code ci-dessus qui m'échappe ?
c'est dans le "niveau de contestabilité".
maintenant, c'est un jugement de valeur. ça reste subjectif, et personel.
Sinon, suite à notre dernière discussion, vous ne m'avez pas dit ce que
vous pensiez de l'utilisation des DynamicMethod couplées aux generics ?
et bien, c'est trés idiot, mais je n'ai pas exactement compris ou m'en
servir une fois que je me suis lancé dans le truc.
d'autre part, ma petite enquete m'a amené à penser que si j'ai besoin de
perfs, je privilegierai la generation de code et la specialisation.
mais pour l'instant, le cout de la genericité est negligeable dans la
balance. ce qui prime est la compilation et le typage "fort".
par exemple, dans le source qui suit, entre le top et le bottom, horsmis des
cas surréalistes de clients qui piquent une crise pour 10 secondes de plus
sur 3 minutes d'execution, je choisirai d'implanter le top.
public delegate T BinaryFunction<T>(T x,T y) ;
public abstract class BinaryOperator<T>
{
protected BinaryOperator()
{ }
public abstract T Compute(T x,T y) ;
}
public static class PlusFunction
{
public static decimal Decimal(decimal x, decimal y) { return x + y; }
public static double Double(double x, double y) { return x + y; }
public static float Single(float x, float y) { return x + y; }
}
public static class PlusOperator
{
public static readonly BinaryOperator<decimal> Decimal = new
DecimalPlus();
public static readonly BinaryOperator<double> Double = new DoublePlus();
public static readonly BinaryOperator<float> Single = new SinglePlus();
private class DecimalPlus : BinaryOperator<decimal>
{
public override decimal Compute(decimal x, decimal y)
{
return x + y;
}
}
private class DoublePlus : BinaryOperator<double>
{
public override double Compute(double x, double y)
{
return x + y;
}
}
private class SinglePlus : BinaryOperator<float>
{
public override float Compute(float x, float y)
{
return x + y;
}
}
}
public static class Stl
{
// 0 : specialisation v
public static T Accumulate1<T>(IEnumerable<T> v, BinaryFunction<T>
function, T zero)
{
T result = zero;
foreach (T x in v)
result = function(result, x);
return result;
}
public static T Accumulate0<T>(IList<T> v, BinaryFunction<T> function, T
zero)
{
T result = zero;
foreach (T x in v)
result = function(result, x);
return result;
}
public static T Accumulate2<T>(T[] v, BinaryFunction<T> function, T zero)
{
T result = zero;
foreach (T x in v)
result = function(result, x);
return result;
}
// 1 : T -> decimal
public static decimal Accumulate1d(IEnumerable<decimal> v,
BinaryFunction<decimal> function, decimal zero)
{
decimal result = zero;
foreach (decimal x in v)
result = function(result, x);
return result;
}
public static decimal Accumulate0d(IList<decimal> v,
BinaryFunction<decimal> function, decimal zero)
{
decimal result = zero;
foreach (decimal x in v)
result = function(result, x);
return result;
}
public static decimal Accumulate2d(decimal[] v, BinaryFunction<decimal>
function, decimal zero)
{
decimal result = zero;
foreach (decimal x in v)
result = function(result, x);
return result;
}
// 2 : function = delegate | class
public static T Accumulate1o<T>(IEnumerable<T> v, BinaryOperator<T>
function, T zero)
{
T result = zero;
foreach (T x in v)
result = function.Compute(result, x);
return result;
}
public static T Accumulate0o<T>(IList<T> v, BinaryOperator<T> function, T
zero)
{
T result = zero;
foreach (T x in v)
result = function.Compute(result, x);
return result;
}
public static T Accumulate2o<T>(T[] v, BinaryOperator<T> function, T zero)
{
T result = zero;
foreach (T x in v)
result = function.Compute(result, x);
return result;
}
public static decimal Accumulate1do(IEnumerable<decimal> v,
BinaryOperator<decimal> function, decimal zero)
{
decimal result = zero;
foreach (decimal x in v)
result = function.Compute(result, x);
return result;
}
public static decimal Accumulate0do(IList<decimal> v,
BinaryOperator<decimal> function, decimal zero)
{
decimal result = zero;
foreach (decimal x in v)
result = function.Compute(result, x);
return result;
}
public static decimal Accumulate2do(decimal[] v, BinaryOperator<decimal>
function, decimal zero)
{
decimal result = zero;
foreach (decimal x in v)
result = function.Compute(result, x);
return result;
}
// non traité : BinaryOperator<decimal> -> DecimalPlus
// 3 : inlining plus |- ?di = ?doi
public static decimal Accumulate1doi(IEnumerable<decimal> v, decimal zero)
{
decimal result = zero;
foreach (decimal x in v)
result = result + x;
return result;
}
public static decimal Accumulate0doi(IList<decimal> v, decimal zero)
{
decimal result = zero;
foreach (decimal x in v)
result = result + x ;
return result;
}
public static decimal Accumulate2doi(decimal[] v, decimal zero)
{
decimal result = zero;
> Je ne comprends pas le "par contre" : il y a une contradiction entre ce principe et le code ci-dessus qui m'échappe ?
c'est dans le "niveau de contestabilité". maintenant, c'est un jugement de valeur. ça reste subjectif, et personel.
Sinon, suite à notre dernière discussion, vous ne m'avez pas dit ce que vous pensiez de l'utilisation des DynamicMethod couplées aux generics ?
et bien, c'est trés idiot, mais je n'ai pas exactement compris ou m'en servir une fois que je me suis lancé dans le truc. d'autre part, ma petite enquete m'a amené à penser que si j'ai besoin de perfs, je privilegierai la generation de code et la specialisation. mais pour l'instant, le cout de la genericité est negligeable dans la balance. ce qui prime est la compilation et le typage "fort".
par exemple, dans le source qui suit, entre le top et le bottom, horsmis des cas surréalistes de clients qui piquent une crise pour 10 secondes de plus sur 3 minutes d'execution, je choisirai d'implanter le top.
public delegate T BinaryFunction<T>(T x,T y) ;
public abstract class BinaryOperator<T> { protected BinaryOperator() { }
public abstract T Compute(T x,T y) ; }
public static class PlusFunction { public static decimal Decimal(decimal x, decimal y) { return x + y; } public static double Double(double x, double y) { return x + y; } public static float Single(float x, float y) { return x + y; } }
public static class PlusOperator { public static readonly BinaryOperator<decimal> Decimal = new DecimalPlus(); public static readonly BinaryOperator<double> Double = new DoublePlus(); public static readonly BinaryOperator<float> Single = new SinglePlus();
private class DecimalPlus : BinaryOperator<decimal> { public override decimal Compute(decimal x, decimal y) { return x + y; } } private class DoublePlus : BinaryOperator<double> { public override double Compute(double x, double y) { return x + y; } } private class SinglePlus : BinaryOperator<float> { public override float Compute(float x, float y) { return x + y; } } }
public static class Stl { // 0 : specialisation v public static T Accumulate1<T>(IEnumerable<T> v, BinaryFunction<T> function, T zero) { T result = zero;
foreach (T x in v) result = function(result, x);
return result; } public static T Accumulate0<T>(IList<T> v, BinaryFunction<T> function, T zero) { T result = zero;
foreach (T x in v) result = function(result, x);
return result; } public static T Accumulate2<T>(T[] v, BinaryFunction<T> function, T zero) { T result = zero;
foreach (T x in v) result = function(result, x);
return result; }
// 1 : T -> decimal public static decimal Accumulate1d(IEnumerable<decimal> v, BinaryFunction<decimal> function, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = function(result, x);
return result; } public static decimal Accumulate0d(IList<decimal> v, BinaryFunction<decimal> function, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = function(result, x);
return result; } public static decimal Accumulate2d(decimal[] v, BinaryFunction<decimal> function, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = function(result, x);
return result; }
// 2 : function = delegate | class public static T Accumulate1o<T>(IEnumerable<T> v, BinaryOperator<T> function, T zero) { T result = zero;
foreach (T x in v) result = function.Compute(result, x);
return result; } public static T Accumulate0o<T>(IList<T> v, BinaryOperator<T> function, T zero) { T result = zero;
foreach (T x in v) result = function.Compute(result, x);
return result; } public static T Accumulate2o<T>(T[] v, BinaryOperator<T> function, T zero) { T result = zero;
foreach (T x in v) result = function.Compute(result, x);
return result; } public static decimal Accumulate1do(IEnumerable<decimal> v, BinaryOperator<decimal> function, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = function.Compute(result, x);
return result; } public static decimal Accumulate0do(IList<decimal> v, BinaryOperator<decimal> function, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = function.Compute(result, x);
return result; } public static decimal Accumulate2do(decimal[] v, BinaryOperator<decimal> function, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = function.Compute(result, x);
return result; }
// non traité : BinaryOperator<decimal> -> DecimalPlus
// 3 : inlining plus |- ?di = ?doi public static decimal Accumulate1doi(IEnumerable<decimal> v, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = result + x;
return result; } public static decimal Accumulate0doi(IList<decimal> v, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = result + x ;
return result; } public static decimal Accumulate2doi(decimal[] v, decimal zero) { decimal result = zero;
foreach (decimal x in v) result = result + x ;
return result; } }
Zazar
Bonjour,
et bien, c'est trés idiot, mais je n'ai pas exactement compris ou m'e n servir une fois que je me suis lancé dans le truc.
Le but c'est de se débarrasser des BinaryFunction, BinaryOperator, PlusFonction, ... Vous créez une classe OperatorFactory<T> (par exemple) qui contient une méthode GetPlusOperator(). Dans le constructeur static, vous générez une DynamicMethod qui calcu le a + b où a et b sont de type T et lors des appels à GetPlusOperator() vous renvoyez la méthode générée. Ensuite les méthodes de votre classe Stl n'ont plus à recevoir la BinaryFunction en paramètre, elles vont la chercher directement aupré s de l'OperatorFactory.
On y perd un petit peu en typage fort car plus rien n'empêche à la compilation d'utiliser la classe OperatorFactory sur un type n'implémentant pas les opérations de base, mais 1) je doute que ce so it une erreur courante 2) vu que les méthodes sont générées dans le constructeur static, l'erreur est trés facilement repérable et trés tôt.
Par contre, on n'est plus obligé de réimplémenter manuellement tout es les opérations pour chacun des types et les appels aux méthodes de St l sont plus naturels. En poussant le raisonnement un peu plus loin, on doit pouvoir aussi générer le zero automatiquement, mais là je ne vois rien de fiable.
-- Zazar
Bonjour,
et bien, c'est trés idiot, mais je n'ai pas exactement compris ou m'e n
servir une fois que je me suis lancé dans le truc.
Le but c'est de se débarrasser des BinaryFunction, BinaryOperator,
PlusFonction, ...
Vous créez une classe OperatorFactory<T> (par exemple) qui contient une
méthode GetPlusOperator().
Dans le constructeur static, vous générez une DynamicMethod qui calcu le
a + b où a et b sont de type T et lors des appels à GetPlusOperator()
vous renvoyez la méthode générée.
Ensuite les méthodes de votre classe Stl n'ont plus à recevoir la
BinaryFunction en paramètre, elles vont la chercher directement aupré s
de l'OperatorFactory.
On y perd un petit peu en typage fort car plus rien n'empêche à la
compilation d'utiliser la classe OperatorFactory sur un type
n'implémentant pas les opérations de base, mais 1) je doute que ce so it
une erreur courante 2) vu que les méthodes sont générées dans le
constructeur static, l'erreur est trés facilement repérable et trés tôt.
Par contre, on n'est plus obligé de réimplémenter manuellement tout es
les opérations pour chacun des types et les appels aux méthodes de St l
sont plus naturels.
En poussant le raisonnement un peu plus loin, on doit pouvoir aussi
générer le zero automatiquement, mais là je ne vois rien de fiable.
et bien, c'est trés idiot, mais je n'ai pas exactement compris ou m'e n servir une fois que je me suis lancé dans le truc.
Le but c'est de se débarrasser des BinaryFunction, BinaryOperator, PlusFonction, ... Vous créez une classe OperatorFactory<T> (par exemple) qui contient une méthode GetPlusOperator(). Dans le constructeur static, vous générez une DynamicMethod qui calcu le a + b où a et b sont de type T et lors des appels à GetPlusOperator() vous renvoyez la méthode générée. Ensuite les méthodes de votre classe Stl n'ont plus à recevoir la BinaryFunction en paramètre, elles vont la chercher directement aupré s de l'OperatorFactory.
On y perd un petit peu en typage fort car plus rien n'empêche à la compilation d'utiliser la classe OperatorFactory sur un type n'implémentant pas les opérations de base, mais 1) je doute que ce so it une erreur courante 2) vu que les méthodes sont générées dans le constructeur static, l'erreur est trés facilement repérable et trés tôt.
Par contre, on n'est plus obligé de réimplémenter manuellement tout es les opérations pour chacun des types et les appels aux méthodes de St l sont plus naturels. En poussant le raisonnement un peu plus loin, on doit pouvoir aussi générer le zero automatiquement, mais là je ne vois rien de fiable.