2009-07-27 12 views
10

Ich habe einige sehr ineffiziente Code, in denen viele Zeilen erscheinen 4 mal, wie ich durch Permutationen mit "<" und ">" Operationen und eine Vielzahl von Variablen und Konstanten. Es scheint, dass es einen Weg gibt, die Funktion einmal zu schreiben und die Operatoren zusammen mit den notwendigerweise sich ändernden Werten und "ref" Variablen zu übergeben. Welche Technik muss ich lernen? "Delegierte" wurden vorgeschlagen, aber ich sehe nicht, wie man sie auf diese Weise benutzt. Dies ist in C# 2.0, VS2005, aber wenn die Technik generisch ist und auch mit C++ verwendet werden kann, wäre das großartig.Übergeben eines Operators mit anderen Parametern

Antrag auf einige Codes: Es erscheint in vielen Formen, mit verschiedenen "<" und ">" Zeichen sowie eine Mischung aus "+" und "-" Zeichen:

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

Würden Sie in der Lage sein, einen Code zu schreiben? –

+0

Könnte jemand diesen Code formatieren? Könnten Sie uns auch etwas mehr Code geben? Im Moment ist es schwer zu sehen, was alles variieren wird - Wird es immer gegen 'move [check]' sein, und woher kommt 'adjust'? Ihre aktuelle Vermutung zu einer Methodensignatur kann helfen. –

+0

Danke an Rob für die Sichtbarkeit meines Codes! "adjust" ist eine Klassenvariable und ich ändere es abhängig von der Bildschirmauflösung und dem Computer, auf dem ich das Programm vorführe. move ist ein Array von Instanzen einer Klasse In 2 der 4 Varianten des Codes würde ich uns Xpos, nicht YPos. Auch 2 der 4 haben <, 2 have >. Alles mit> würde ein + vor der adjust-Variable verwenden und umgekehrt. Außerdem verwendet man lcac_c.top, man benutzt lcac_c.right, etc. Ich möchte, dass alle diese übergeben werden. – user32848

Antwort

11

In C++ verwenden, um die std::less und std::greater functors. Beide Methoden erben std::binary_function, daher sollte Ihre generische Funktion Instanzen dieses Typs akzeptieren.

In .NET ist das Äquivalent zu std::binary_functionFunc<T, U, R>. Es gibt keine Entsprechungen zu std::less und std::greater, aber es ist ziemlich trivial, sie zu erstellen. Siehe das folgende Beispiel.

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

Hinweis, der obige Code verwendet die Func<> Klasse von .NET 3.5. Wenn dies nicht akzeptabel ist, sollten Sie einen eigenen Delegaten definieren.

C++ Aufruf Beispiel:

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# Invokation Beispiel:

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: I am Beispiel der Funktors Klasse korrigiert, wie die Anwendung < oder> Betreiber auf einen generischen Typ doesn‘ t funktionieren (genauso wie bei C++ - Vorlagen).

+1

Das ist eine viel bessere Antwort als meine. –

+0

In dem obigen C# -Beispiel ist Functor in .Net 2.0 verfügbar? Ich kann den obigen Code nicht funktionieren lassen? Muss ich eine Referenz hinzufügen? – user32848

+0

Nein, Functor ist keine Standard-.NET-Klasse - Sie müssen es selbst schreiben. Außerdem enthält .NET 2.0 kein Func <> (es befindet sich in System.Core.dll in .NET 3.5), daher müssen Sie stattdessen System.Predicate verwenden. –

2

In C# Verwenden Sie Delegaten, um die Operation "<" und ">" an den Code zu übergeben, der die Arbeit ausführt.

C# Beispiel:

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

Sie sollten auch prüfen, ob die Delegierten Sie als Paramater bekommen nicht NULL ist.

Dies ist die C-Methode so zu tun:

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

Idiomatic C++ würde tatsächlich Funktionsobjekte und keine Funktionszeiger verwenden (dies würde insbesondere die Verwendung von 'std: less' und anderen solchen Bestandsfunktoren ermöglichen). –

0

Sie können Operatoren übergeben, indem Sie sie ähnlich wie den Enum Operator in dieser Comparer-Klasse definieren. und rufen Sie dann die Funktion wie folgt aus:

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

Bitte denken Sie daran, einige Details und Erklärungen hinzuzufügen, um Ihre Antwort zu unterstützen, um anderen zu helfen –

Verwandte Themen