2009-07-27 7 views
10

J'ai un code TRÈS inefficace dans lequel plusieurs lignes apparaissent 4 fois que je passe par des permutations avec des opérations "<" et ">" et une variété de variables et de constantes. Il semblerait qu'il y ait un moyen d'écrire la fonction une fois et de passer dans les opérateurs avec les variables qui changent et les variables "ref". Quelle technique dois-je apprendre? Des "délégués" ont été suggérés mais je ne vois pas comment les utiliser de cette manière. C'est en C# 2.0, VS2005, mais si la technique est générique et peut aussi être utilisée en C++, ce serait génial.Passer un opérateur avec d'autres paramètres

Demande d'un code: Le suivant apparaît dans de nombreuses formes, avec différentes « < » et « > » signes ainsi qu'un mélange de « + » et « - » signes:

if (move[check].Ypos - move[check].height/200.0D < LayoutManager.VISIO_HEIGHT - lcac_c.top) 
{ 
    move[check].Ypos = move[check].Ypos + adjust; 
. 
. 
. 
+2

Seriez-vous en mesure d'afficher un code? –

+0

Quelqu'un pourrait-il formater ce code? Aussi, pourriez-vous nous donner un peu plus de code? À l'heure actuelle, il est difficile de voir ce que tout va varier - Sera-t-il toujours contre 'move [check]', et d'où vient le 'adjust'? Votre estimation actuelle d'une signature de méthode peut aider. –

+0

Merci à Rob pour avoir nettoyé la visibilité de mon code! "adjust" est une variable de classe et je la change en fonction de la résolution de l'écran et de l'ordinateur sur lequel le programme est exécuté. move est un tableau d'instances d'une classe Dans 2 des 4 variantes du code je voudrais nous Xpos, pas YPos. En outre 2 des 4 ont <, 2 have >. Tout avec> utiliserait un + avant la variable d'ajustement et vice versa. En outre, on utilise lcac_c.top, on utilise lcac_c.right, etc. Je voudrais que tout cela soit passé. – user32848

Répondre

11

En C++, utilisez les std::less et std::greater foncteurs. Ces deux méthodes héritent de std::binary_function. Votre fonction générique doit donc accepter les instances de ce type. En .NET, l'équivalent de std::binary_function est Func<T, U, R>. Il n'y a pas d'équivalents à std::less et std::greater, mais il est assez trivial de les créer. Voir l'exemple suivant.

static class Functor 
{ 
    static Func<T, T, bool> Greater<T>() 
     where T : IComparable<T> 
    { 
     return delegate(T lhs, T rhs) { return lhs.CompareTo(rhs) > 0; }; 
    } 

    static Func<T, T, bool> Less<T>() 
     where T : IComparable<T> 
    { 
     return delegate(T lhs, T rhs) { return lhs.CompareTo(rhs) < 0; }; 
    } 
} 

Remarque, le code ci-dessus utilise la classe Func<> de .NET 3.5. Si cela n'est pas acceptable, envisagez de définir votre propre délégué.

C++ Exemple d'appel:

void DoWork(const std::binary_function<int, int, bool>& myOperator, 
      int arg1, int arg2) 
{ 
    if (myOperator(arg1, arg2)) { /* perform rest of work */ } 
} 

void main() 
{ 
    DoWork(std::less<int>(), 100, 200); 
    DoWork(std::greater<int>(), 100, 200); 
} 

C# invocation exemple:

void DoWork(Func<int, int, bool> myOperator, int arg1, int arg2) 
{ 
    if (myOperator(arg1, arg2)) { /* perform rest of work */ } 
} 

void main() 
{ 
    DoWork(Functor.Less<int>(), 100, 200); 
    DoWork(Functor.Greater<int>(), 100, 200); 
} 

EDIT: Je corrigeais l'exemple de la classe foncteur comme application < ou> les opérateurs à un type générique n » t travail (de la même manière que pour les templates C++).

+1

C'est une bien meilleure réponse que la mienne. –

+0

Dans l'exemple C# ci-dessus, Functor est-il disponible dans .Net 2.0? Je ne peux pas faire fonctionner le code ci-dessus? Ai-je besoin d'ajouter une référence? – user32848

+0

Non, Functor n'est pas une classe .NET standard - vous devez l'écrire vous-même. En outre, .NET 2.0 ne contient pas Func <> (il est dans System.Core.dll dans .NET 3.5), vous devrez donc utiliser System.Predicate à sa place. –

2

en C# utilisez les délégués pour passer l'opération "<" et ">" au code qui fait le travail.

C# Exemple:

public delegate bool BooleanOperatorDelegate(int a, int b) 

class OperatorsImplementer { 
    public bool OperatorLess(int a, int b) { 
     return a < b; 
    } 
} 

class AnotherOperatorsImplementer { 
    public bool OperatorLess(int a, int b) { 
     return (a + 1) < (b - 1); 
    } 
} 

class OperatorUser { 
    int DoSomethingObscene(int a, int b, BooleanOperatorDelegate operator) { 
     if (operator(a, b)) { 
      return 5; 
     } 
     else { 
      return -5; 
     } 
    } 
} 

Vous devriez également vérifier que le délégué que vous obtenez en tant que paramater n'est pas NULL.

Ceci est la méthode C pour le faire:

bool (*operator_func)(float a, float b) 
+0

Idiomatic C++ utiliserait réellement des objets de fonction et non des pointeurs de fonction (en particulier, cela permettrait l'utilisation de 'std: less' et d'autres foncteurs de stock). –

0

Vous pouvez passer des opérateurs en les définissant de la même manière que l'opérateur Enum dans cette classe Comparer; puis appeler la fonction comme ceci:

if (IsTrue(var1, Operator.GreaterThanOrEqual, var2)) 
    Console.WriteLine("var1 is greater than var2"); 
else 
    Console 
     .WriteLine("Unfortunately var1 is not greater than or equal var2. Sorry about that."); 

 public static class Comparer 
{ 
    public static bool IsTrue<T, U>(T value1, Operator comparisonOperator, U value2) 
       where T : U 
       where U : IComparable 
    { 
     switch (comparisonOperator) 
     { 
      case Operator.GreaterThan: 
       return value1.CompareTo(value2) > 0; 
      case Operator.GreaterThanOrEqual: 
       return value1.CompareTo(value2) >= 0; 
      case Operator.LessThan: 
       return value1.CompareTo(value2) < 0; 
      case Operator.LessThanOrEqual: 
       return value1.CompareTo(value2) <= 0; 
      case Operator.Equal: 
       return value1.CompareTo(value2) == 0; 
      default: 
       return false; 
     } 
    } 

    public enum Operator 
    { 
     GreaterThan = 1, 
     GreaterThanOrEqual = 2, 
     LessThan = 3, 
     LessThanOrEqual = 4, 
     Equal = 5 
    } 
} 
+0

S'il vous plaît envisager d'ajouter quelques détails et des explications pour soutenir votre réponse afin d'aider les autres –

Questions connexes