OVH Cloud OVH Cloud

qu'est-ce qui est meilleur?

11 réponses
Avatar
julien
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 A:
ArrayList list = new ArrayList();

modifyA1(ref list);
modifyA2(ref list);
modifyA3(ref list);
modifyA4(ref list);


cas B:
ArrayList list = modifyB1();
list = modifyB2(list);
list = modifyB3(list);
list = modifyB4(list);


Merci
Julien

10 réponses

1 2
Avatar
Frédéric Queudret [MS]
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" 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 A:
ArrayList list = new ArrayList();

modifyA1(ref list);
modifyA2(ref list);
modifyA3(ref list);
modifyA4(ref list);


cas B:
ArrayList list = modifyB1();
list = modifyB2(list);
list = modifyB3(list);
list = modifyB4(list);


Merci
Julien


Avatar
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 A:
ArrayList list = new ArrayList();

modifyA1(ref list);
modifyA2(ref list);
modifyA3(ref list);
modifyA4(ref list);


cas B:
ArrayList list = modifyB1();
list = modifyB2(list);
list = modifyB3(list);
list = modifyB4(list);


Merci
Julien


Avatar
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
Avatar
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):



Dans le cas général, le mieux est :

ArrayList list = new ArrayList();

modifyA1(list);
modifyA2(list);
modifyA3(list);
modifyA4(list);

ArrayList est un type référence : pas besoin d'utiliser ref.


cas A:
ArrayList list = new ArrayList();

modifyA1(ref list);
modifyA2(ref list);
modifyA3(ref list);
modifyA4(ref list);



ref est inutile dans ce cas là (voire dangereux).

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
Avatar
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
Avatar
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
Avatar
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):




Dans le cas général, le mieux est :

ArrayList list = new ArrayList();

modifyA1(list);
modifyA2(list);
modifyA3(list);
modifyA4(list);

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
Avatar
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
Avatar
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;
}
}
Avatar
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
1 2