2009-07-27 8 views
10

Ho un codice MOLTO inefficiente in cui molte righe appaiono 4 volte mentre passo attraverso le permutazioni con operazioni "<" e ">" e una varietà di variabili e costanti. Sembrerebbe che ci sia un modo per scrivere la funzione una volta e passare gli operatori insieme ai valori necessariamente variabili e alle variabili "ref". Che tecnica devo imparare? "Delegati" sono stati suggeriti ma non vedo come usarli in questo modo. Questo è in C# 2.0, VS2005, ma se la tecnica è generica e può essere usata anche con C++, sarebbe grandiosa.Passaggio di un operatore insieme ad altri parametri

Richiesta di codice: Il seguente appare in molte forme, con diversi "<" e ">" segni così come un mix di "+" e "-" segni:

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

Vuoi essere in grado di inviare un certo codice? –

+0

Qualcuno potrebbe formattare quel codice? Inoltre, potresti darci un po 'di codice in più? In questo momento è difficile vedere cosa cambierà tutto - sarà sempre contro 'move [check]', e da dove proviene 'adjust'? La tua attuale ipotesi su una firma del metodo può aiutare. –

+0

Grazie a Rob per la pulizia della visibilità del mio codice! "adjust" è una variabile di classe e la cambio a seconda della risoluzione dello schermo e del computer su cui sto dimostrando il programma. move è una matrice di istanze di una classe In 2 delle 4 varianti del codice, io vorrei Xpos, non YPos. Anche 2 dei 4 hanno <, 2 have >. Qualsiasi cosa con> usa un + prima della variabile di regolazione e viceversa. Inoltre, uno usa lcac_c.top, uno usa lcac_c.right, ecc. Vorrei che tutti questi fossero passati. – user32848

risposta

11

In C++, utilizzare i std::less e std::greater funtori. Entrambi questi metodi ereditano std::binary_function, quindi la tua funzione generica dovrebbe accettare istanze di questo tipo.

In .NET, l'equivalente a std::binary_function è Func<T, U, R>. Non ci sono equivalenti a std::less e std::greater, ma è abbastanza banale da crearli. Vedi il seguente esempio.

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; }; 
    } 
} 

nota, il codice precedente utilizza la classe Func<> da .NET 3.5. Se questo non è accettabile, prendere in considerazione la definizione di un proprio delegato.

C++ invocazione esempio:

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# invocazione esempio:

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: ho corretto l'esempio della classe funtore come applicabile < o> operatori di un tipo generico doesn' lavoro (nello stesso modo con i modelli C++).

+1

Questa è una risposta molto migliore della mia. –

+0

Nell'esempio C# precedente, Functor è disponibile in .Net 2.0? Non riesco a far funzionare il codice sopra? Devo aggiungere un riferimento? – user32848

+0

No, Functor non è una classe .NET standard, è necessario scriverla da soli. Inoltre, .NET 2.0 non contiene Func <> (è in System.Core.dll in .NET 3.5), quindi sarà necessario utilizzare System.Predicate al suo posto. –

2

in C# utilizzare i delegati per passare l'operazione "<" e ">" al codice che sta facendo il lavoro.

C# Esempio:

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; 
     } 
    } 
} 

Si dovrebbe anche controllare che il delegato si ottiene come paramater non è NULL.

Questo è il metodo C per farlo:

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

Il C++ idiomatico userebbe effettivamente gli oggetti funzione e non i puntatori di funzione (in particolare, questo abiliterebbe l'uso di 'std: less' e di altri funtori di questo tipo). –

0

È possibile passare gli operatori definendoli in modo simile all'operatore Enum in questa classe Comparer; e quindi chiamare la funzione in questo modo:

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

Ti preghiamo di aggiungere alcuni dettagli e spiegazioni per supportare la tua risposta al fine di aiutare gli altri –

Problemi correlati