2017-02-14 1 views
0

EDIT: À l'origine, l'exemple de cet article traitait des codes de hachage. Vous verrez donc des commentaires utilisant param.GetHashCode(), plutôt que (1 + param). Pour aller plus loin, j'ai changé les fonctions pour en calculer une plus la valeur absolue d'un certain nombre. Disons que je veux créer une fonction qui calcule la valeur absolue d'un entier (sans utiliser Math.Abs). Je pourrais écrire quelque chose de similaire à:C# - Limitation de la portée à l'instruction ternaire

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

Je cherche à limiter la portée de onePlusParm à l'intérieur de la déclaration ternaire - quelque chose de similaire à:

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

Je comprends que ce n'est pas valide C# , mais cela prouve un bon exemple pour ce que j'essaie d'accomplir - créer une variable qui n'existe que dans le cadre d'un opérateur ternaire.

+3

« Je cherche à compresser cette méthode jusqu'à une ligne". Pouvez-vous expliquer la raison pour laquelle vous devez faire cela? – openshac

+1

vous pourriez faire 'int i; return i = param.GetHashCode()> 0? i: -i; '... je ne le ferais pas mais tu pourrais. –

+0

@openshac, il s'agit plus de limiter la portée que toute autre chose. Si la fonction était beaucoup plus grande, j'existerais tout au long de la fonction. L'utilisation d'une déclaration dans l'instruction ternaire limiterait la portée à l'intérieur du ternaire - une fois l'instruction terminée, i est supprimé. –

Répondre

3

Les parties d'une expression ternaire sont des expressions. Si les concepteurs de langage acceptaient ce que vous demandez, ils le feraient probablement pour toutes les expressions plutôt que pour les expressions ternaires. Vous seriez également en mesure de faire if ((int n = foo()) != 0) bar(n);.

En C#, les déclarations sont des instructions, pas des expressions. Donc la réponse est non, vous ne pouvez pas faire cela. Cependant, la déclaration for peut prendre une déclaration, de sorte que le plus proche, vous pouvez obtenir une déclaration unique est la suivante:

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

qui est techniquement une seule déclaration, mais un composé d'un, et sur deux lignes. Mais ça a l'air horrible et je ne l'écrirais pas comme ça.

Si votre principale préoccupation est de minimiser la portée de i, utilisez une petite portée pour elle:

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

Merci pour l'explication. Le but de ma question était de limiter la portée du code i - pas nécessairement propre, donc c'est parfait. –

1

Je voudrais simplement écrire:

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

ou

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

    return Math.Abs(hashCode); 
} 

La facilité de lecture, la maintenabilité et plus important encore dans ce cas évitent premature optimization which is the root of all evil.

Si vous êtes vraiment inquiet au sujet de la performance, alors faites le profil de votre code et voyez où se trouvent vos plus gros goulots d'étranglement. Je serais surpris si GetPosiitiveHash() cause le plus gros goulot d'étranglement. Vous voudrez peut-être jeter un oeil à la .Net Framework source code pour String.GetHashCode(). Vous verrez qu'un opérateur ternaire aura une économie minime comparé à ce qui se passe dans la méthode GetHashCode().

Il faut se rappeler:

La version complète de la citation est « Nous devons oublier les petits efficacité, par exemple environ 97% du temps: l'optimisation prématurée est la racine de tous les maux. » et je suis d'accord avec ça. Il ne vaut généralement pas passer beaucoup de temps à micro-optimisation du code avant son évident où les goulots d'étranglement de performance sont.

de The fallacy of premature optimization

+0

Le concept que j'ai donné était plus un exemple que toute autre chose. J'explorais la limitation de la portée d'une variable à l'intérieur de l'instruction ternaire - pas nécessairement l'optimisation du bloc de code exact que j'ai fourni. Cela étant dit, c'est certainement une citation à retenir. –

+0

OK, cela peut valoir la peine de modifier votre question pour remplacer le GetHashCode() par quelque chose de trivial, cela obscurcit l'optimisation que vous essayez d'obtenir. – openshac

+0

C'est un bon point. Je le ferai. –

1

Vous pouvez remplacer avoir une variable de données (i) portée d'avoir une variable de fonction portée. L'avantage est qu'une fonction est plus susceptible d'être écrite qu'une seule fois et ne risque pas d'être mal utilisée.

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

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

Mon expérience avec les expressions lambda est limitée, mais j'aime ça. Je vais regarder plus dans les variables de fonction - merci. –

0

En plus simplement créer un nouveau bloc, vous pouvez également utiliser la fonction intégrée de valeur absolue Math.Abs(...) ou définir votre propre lambda/fonction;

... construit en ...

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

... fonction statique ...

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

Et mon tentative

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

(Bien sûr, votre code (et le mien) est mauvais, vous devez diviser votre méthode en 2 plus petits)

et la question mise à jour

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