2017-02-14 6 views
0

EDIT: Ursprünglich hatte das Beispiel dieses Beitrags mit Hash-Codes behandelt, so dass Sie einige Kommentare mit param.GetHashCode() statt (1 + param) sehen werden. Um mehr auf den Punkt zu kommen, habe ich die Funktionen geändert, um eins plus den absoluten Wert einer Zahl zu berechnen.C# - Begrenzt den Geltungsbereich der ternären Anweisung

Angenommen, ich möchte eine Funktion erstellen, die den absoluten Wert einer ganzen Zahl berechnet (ohne Math.Abs ​​zu verwenden).

int absoluteValueOfOnePlus(int param) 
{ 
    int onePlusParam= 1 + param; 
    return ((onePlusParam> 0) ? (onePlusParam) : (-onePlusParam)); 
} 

Ich suche den Umfang der onePlusParm innerhalb des ternären Aussage zu begrenzen - etwas Ähnliches wie: Ich könnte etwas Ähnliches schreiben

int absoluteValueOfOnePlus(intparam) 
{ 
    return (((int onePlusParam = 1 + param) > 0) ? (onePlusParam) : (-onePlusParam)); 
} 

Ich verstehe, dass dies nicht gültig C# , aber es ist ein gutes Beispiel für das, was ich zu tun versuche - erstelle eine Variable, die nur im Rahmen eines ternären Operators existiert.

+3

„Ich suche diese Methode zu komprimieren, bis auf eine Linie". Können Sie den Grund erklären, warum Sie dies tun müssen? – openshac

+1

könnten Sie 'int ich tun; zurückgeben i = param.GetHashCode()> 0? ich: -i; '... ich würde nicht, aber du könntest es. –

+0

@openshac, es geht mehr darum, den Umfang zu begrenzen als alles andere. Wenn die Funktion viel größer wäre, würde ich im Rest der Funktion existieren. Die Verwendung einer Deklaration in der ternären Anweisung würde den Geltungsbereich auf das Ternär beschränken - nachdem die Aussage abgeschlossen ist, wird i gelöscht. –

Antwort

3

Die Teile eines ternären Ausdrucks sind Ausdrücke. Wenn die Sprachdesigner zulassen würden, wonach Sie fragen, würden sie das wahrscheinlich für alle Ausdrücke tun und nicht nur für ternäre Ausdrücke. Sie könnten dann auch if ((int n = foo()) != 0) bar(n); tun.

In C# sind Deklarationen Anweisungen, keine Ausdrücke. Also die Antwort ist nein, das kannst du nicht tun. Allerdings kann die for Aussage eine Erklärung nehmen, so die nächstgelegene Sie zu einer einzigen Anweisung bekommen können, ist dies:

for (int i = param.GetHashCode();;) 
    return (i > 0) ? i : -i; 

, die technisch eine einzige Erklärung ist, wenn auch eine Verbindung ein, und auf zwei Linien. Aber das sieht schrecklich aus und ich würde es nicht so schreiben.

Wenn Ihr Hauptanliegen ist, den Umfang der i minimiert, dann einen kleinen Spielraum für die es verwenden:

int positiveHash(string param) 
{ 
    // Some statements here... 
    // ... 

    // Start a small scope 
    { 
     int i = param.GetHashCode(); 
     if (...) 
      return ((i > 0) ? (i) : (-i)); 
    } 

    // Some more C# statements here. 
    // i is out of scope here. 
} 
+0

Vielen Dank für die Erklärung. Das Ziel meiner Frage war, den Umfang von i zu begrenzen - nicht unbedingt sauberer Code, also ist das perfekt. –

1

Ich würde einfach schreiben:

int GetPositiveHash(string param) 
{ 
    return Math.Abs(param.GetHashCode()); 
} 

oder

int GetPositiveHash(string param) 
{ 
    int hashCode = param.GetHashCode(); 

    return Math.Abs(hashCode); 
} 

Die Hilfsmittel Lesbarkeit, Wartbarkeit und vor allem in diesem Fall vermeiden premature optimization which is the root of all evil.

Wenn Sie sich wirklich Sorgen über die Leistung machen, dann profilieren Sie den Code und sehen Sie, wo Ihre größten Engpässe sind. Ich wäre überrascht, wenn GetPosiitiveHash() den größten Engpass verursacht.

Sie können sich die .Net Framework source code für String.GetHashCode() ansehen. Sie werden sehen, dass ein ternärer Operator im Vergleich zu dem, was innerhalb der GetHashCode() Methode vor sich geht, eine minimale Einsparung haben wird.

Es lohnt sich zu erinnern:

Die Vollversion des Zitats ist „Wir über kleine Effizienzen vergessen sollte, sagen wir etwa 97% der Zeit. Vorzeitige Optimierung der Wurzel allen Übels ist“ und ich stimme dem zu. Es ist in der Regel nicht wert verbringen viel Zeit Mikro-Optimierung Code vor seiner offensichtlichen wo die Leistungsengpässe sind.

von The fallacy of premature optimization

+0

Das Konzept, das ich gab, war mehr ein Beispiel als alles andere. Ich untersuchte, wie man den Gültigkeitsbereich einer Variablen auf die ternäre Aussage beschränkte - nicht unbedingt die Optimierung des exakten Codeblocks, den ich zur Verfügung stellte. Davon abgesehen ist dies definitiv ein Zitat, an das man sich zu erinnern lohnt. –

+0

OK, es könnte sich lohnen, Ihre Frage zu modifizieren, um GetHashCode() durch etwas Triviales zu ersetzen, es verdunkelt die Optimierung, die Sie erreichen möchten. – openshac

+0

Das ist ein fairer Punkt. Ich werde es tun. –

1

könnten Sie ersetzen eine Datenvariable mit (i) in ihrem Umfang eine Funktion Variable in ihrem Umfang zu haben. Der Vorteil ist, dass eine Funktion eher nur einmal geschrieben wird und wahrscheinlich nicht missbraucht wird.

int positiveHash(string param) 
{ 
    Func<int, int> absoluteValue = i => (i > 0) ? i : -1; 

    return absoluteValue(param.GetHashCode()); 
} 
+0

Meine Erfahrung mit Lambda-Ausdrücken ist begrenzt, aber ich mag das. Ich schaue mehr in Funktionsvariablen - danke. –

0

Neben nur einen neuen Block zu schaffen Sie auch die eingebauten Absolutwertfunktion Math.Abs(...) oder definieren Sie Ihre eigene Lambda/Funktion nutzen zu können;

... eingebaut ...

public static int hash(string param) 
{ 
    return Math.Abs(param.GetHashCode()); 
} 

... Lambda ...

static Func<int, int> abs = i => i > 0 ? i : -i; 
public static int hash(string param) 
{ 
    return abs(param.GetHashCode()); 
} 

... statische Funktion ...

static int Abs(int i) 
{ 
    return i > 0 ? i : -i; 
} 
public static int hash(string param) 
{ 
    return Abs(param.GetHashCode()); 
} 
0

Und mein Versuch

static int positiveHash(string param) 
{ 
    return new List<string>() {param}.Select(s => s.GetHashCode()).Select(i => (i > 0) ? (i) : (-i)).Single(); 
} 

(Natürlich Code (und mir) ist schlecht, müssen Sie Ihre Methode in zwei kleinere aufteilen)

und die aktualisierte Frage

static int absoluteValueOfOnePlus(int intparam) 
{ 
     return new List<int> { intparam }.Select(n => n + 1).Select(i => (i > 0) ? (i) : (-i)).Single(); 
} 
Verwandte Themen