2017-02-14 2 views
0

EDIT: Первоначально этот пример сообщения имел дело с хеш-кодами, поэтому вы увидите некоторые комментарии, используя param.GetHashCode(), а не (1 + param). Чтобы получить больше информации, я изменил функции для вычисления одного плюс абсолютное значение некоторого числа.C# - Ограничение объема до трехзначного оператора

Предположим, что я хочу создать функцию, которая вычисляет абсолютное значение некоторого целого числа (без использования Math.Abs). Я мог бы написать что-то подобное:

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

Я ищу, чтобы ограничить сферу onePlusParm в рамках трехкомпонентной заявления - что-то похожее на:

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

Я понимаю, что это не действует C# , но он служит хорошим примером того, что я пытаюсь выполнить, - создайте переменную, которая существует только в области тройного оператора.

+3

«Я ищу, чтобы сжать этот метод вниз одна линия". Можете ли вы объяснить причину, почему вам нужно это делать? – openshac

+1

вы можете сделать 'int i; return i = param.GetHashCode()> 0? i: -i; '... Я бы не мог, но мог. –

+0

@openshac, это больше о возможности ограничения, чем о чем-либо еще. Если бы функция была намного больше, я бы существовал во всей остальной функции. Использование объявления в тернарном выражении ограничило бы область видимости внутри ternary - после завершения инструкции i будет удалена. –

ответ

3

Элементы тернарного выражения являются выражениями. Если бы разработчики языка могли разрешить то, о чем вы просите, они, вероятно, сделают это для всех выражений, а не только для трехмерных выражений. Тогда вы также сможете сделать if ((int n = foo()) != 0) bar(n);.

В C# объявления - это выражения, а не выражения. Так что ответ - нет, вы не можете этого сделать. Однако for оператор может принять декларацию, так что ближайший вы можете добраться до одного оператора заключается в следующем:

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

который является технически один оператор, хотя соединение одного и на двух линиях. Но это выглядит ужасно, и я бы так не писал.

Если вашей главной задачей является минимизация масштабов i, а затем использовать небольшой объем для него:

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

Спасибо за объяснение. Цель моего вопроса заключалась в ограничении объема i - не обязательно чистого кода, поэтому это идеально. –

1

Я бы просто написать:

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

или

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

    return Math.Abs(hashCode); 
} 

Читаемость, ремонтопригодность и, что более важно, в этом случае избегают premature optimization which is the root of all evil.

Если вы действительно беспокоитесь о производительности, прокомментируйте свой код и посмотрите, где находятся ваши самые большие узкие места. Я был бы удивлен, если бы GetPosiitiveHash() стал самым большим узким местом.

Возможно, вам понравится .Net Framework source code для String.GetHashCode(). Вы увидите, что тройной оператор будет иметь минимальную экономию, сравнив то, что происходит внутри метода GetHashCode().

Это стоит вспомнить:

Полная версия котировки «Мы должны забыть о небольших эффективности, скажем, около 97% времени:. Преждевременная оптимизация является корнем всех зол» и я согласен с этим. Его обычно не стоит , тратя много времени на микро-оптимизирующий код до его очевидного места, где стоят .

от The fallacy of premature optimization

+0

Концепция, которую я дал, была скорее примером, чем чем-либо еще. Я изучал ограничение области переменной в пределах тернарного утверждения - не обязательно оптимизацию точного кода, который я предоставил. Это, как говорится, это определенно цитата, о которой стоит помнить. –

+0

ОК, возможно, стоит модифицировать ваш вопрос, чтобы заменить GetHashCode() чем-то тривиальным, он скрывает оптимизацию, которую вы пытаетесь достичь. – openshac

+0

Это справедливая точка. Я сделаю это. –

1

Можно заменить имеющий переменные данные (i) в области, чтобы имеющей переменные функции в области видимости. Преимущество - это функция, более вероятно, будет написана только один раз и вряд ли будет использована неправильно.

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

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

Мой опыт работы с лямбда-выражениями ограничен, но мне это нравится. Я больше посмотрю на функциональные переменные - спасибо. –

0

Кроме того, только создание нового блока можно также использовать встроенную функцию абсолютного значения Math.Abs(...) или определить свою собственную лямбду/функцию;

... встроенный ...

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

... лямбда ...

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

... статическая функция ...

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

И мой попытка

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

(Конечно, ваш код (и мой) это плохо, вам нужно разделить свой метод на 2 меньших)

и обновленный вопрос

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