2010-06-22 3 views
75

Я некоторое время наблюдал, что программисты на C# имеют тенденцию использовать int везде и редко прибегают к uint. Но я почему-то не нашел удовлетворительного ответа.using uint vs int

Если интероперабельность - это ваша цель, uint не должен появляться в публичных API-интерфейсах, потому что не все языки CLI поддерживают целые числа без знака. Но это не объясняет, почему int настолько распространен, даже во внутренних классах. Я подозреваю, что это причина, по которой uint используется экономно в BCL.

В C++, если у вас есть целое число, для которого отрицательные значения не имеют смысла, вы выбираете целое число без знака.

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

Однако при смешивании типов типа int и устройства потребуется дополнительная осторожность и отливка.

Следует ли использовать больше? Зачем?

+0

http://stackoverflow.com/questions/6301/why-is-array-length-an-int-and-not-an-uint – drharris

+0

Только что у меня была дежа вю: D, почти точно такой же вопрос было предложено короткое время назад. – KroaX

+0

Что касается проверок нижних границ (если вам нужно написать свои собственные), вы можете заменить 'if (i < 0 || i > = length)' на 'if (unchecked ((uint) i)> = length)'. Результат IL будет иметь одну (ветвь) инструкцию меньше всего и даст примерно такую ​​же производительность (бесконечно быстрее). Лично я люблю это просто потому, что он царапает мой зуд от проверки нижних границ. Другие, вероятно, возражают против этого из-за «непроверенных», но я утверждаю, что это очень хорошая линия для изучения его смысла, потому что это просто и сразу ясно из контекста, что цель - помогает читателю учиться. – AnorZaken

ответ

47

Ваше мнение о том, почему uint не используется в BCL, является основной причиной, я подозреваю.

UInt32 не соответствует требованиям CLS, что означает, что он полностью неприемлем для использования в публичных API. Если вы собираетесь использовать uint в своем частном API, это будет означать использование конверсий для других типов - и, как правило, проще и безопаснее просто сохранять тип один и тот же.

Я также подозреваю, что это не так часто встречается в разработке C#, даже если C# является единственным используемым языком, прежде всего потому, что он не распространен в BCL. Разработчики, в общем, стараются (к счастью) имитировать стиль структуры, на которой они строятся - в случае с C# это означает, что вы пытаетесь сделать ваши API, общедоступные и внутренние, как можно более похожими на .NET Framework BCL. Это будет означать использование uint экономно.

+0

http://stackoverflow.com/questions/2013116/should-i-use-uint-in-c-for-values-that-cant-be-negative - вопрос, который касается аналогичной темы – Stephan

71

int короче, чем uint.

+2

Я подозреваю, что это очень близко к истине. Зачем использовать 'uint', когда 99% времени (по моему опыту)' int' будет достаточным? –

+0

Да, у меня никогда не было причины использовать 'uint'. И, если мне нужно сохранить большее число, я просто использую 'long'. Приятно иметь возможность использовать -1 в качестве значения ошибки или значения по умолчанию. – jjnguy

+12

@ Justin: «Магические числа», такие как -1, не являются хорошей идеей, в общем. Переключение на длинные означает использование 2x-памяти без причины, а также ... «Единица» определенно ценна, если вам не нужно взаимодействовать с другими API-интерфейсами. –

4

Я предпочитаю uint до int, если отрицательное число действительно находится в диапазоне допустимых значений. В частности, принимая параметр int, но бросая ArgumentException, если число меньше нуля, просто глупо - используйте uint!

Я согласен с тем, что uint недостаточно используется, и я призываю всех остальных использовать его больше.

+7

Очень опасно принимать только uints и не проверять границы. Если кто-то передает отрицательное значение, CLR будет интерпретировать его как большой int, то есть для -1 вы получите uint.maxvalue. Это нежелательное поведение. – Henri

+18

@Henri: C# не имеет неявного преобразования из int в uint, поэтому нет «Если кто-то передает отрицательное значение». Конечно, проверка границ на верхнем пределе по-прежнему подходит (но теперь вам нужна только одна проверка вместо двух). –

0

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

C и C++, однако, имеют глубокие корни в старых системах и встроенных системах, где память разрежена, поэтому программисты используют для тщательного анализа того, какой тип данных использовать. Программисты на C# ленивы, и, поскольку в целом достаточно ресурсов, никто не оптимизирует использование памяти (в общем, не всегда, конечно). Событие, если байт будет достаточным, много программистов на C#, включая меня, просто используют int для простоты. Кроме того, многие функции API принимают ints, поэтому он предотвращает кастинг.

Я согласен с тем, что выбор правильного типа данных является хорошей практикой, но я считаю, что главной мотивацией является лень.

Наконец, выбор целого числа является более математически правильным.Unsigned ints не существуют в математике (только натуральные числа). И поскольку большинство программистов имеют математический фон, использование целого числа является более естественным.

+0

Я бы не сказал, что это лень, хотя лень имеет свои достоинства. Более того, большую часть времени я просто не забочусь о том, что нужно делать, чтобы тратить мозговые циклы на такое решение и просто идти с int. Аппаратное обеспечение, программисты могут быть дорогими. – SWeko

+0

Программисты ленивы. Это плохо. Раймонд сказал, что программисты ненавидят платить налоги! – Wizard79

+0

Я был бы первым, кто сказал бы, что программисты на C# ленивы, но это не обязательно плохо. – ChaosPandion

12

1) Плохая привычка. Шутки в сторону. Даже в C/C++.

Придумайте общую for схемы:

for(int i=0; i<3; i++) 
    foo(i); 

Там нет абсолютно никаких причин, чтобы использовать целое число там. У вас никогда не будет отрицательных значений. Но почти каждый будет делать простой цикл таким образом, даже если он содержит (по крайней мере) две другие ошибки «стиля».

2) int воспринимается как собственный тип машины.

0

Я думаю, что большая часть причины заключается в том, что, когда C впервые вышла, большинство из использованных примеров использовалось int для краткости. Мы радовались тому, что нам не приходилось писать integer, как мы это делали с Fortran и Pascal, и в те дни мы обычно использовали их для мирских вещей, таких как индексы массивов и счетчики циклов. Целочисленные целые числа были специальными случаями для больших чисел, которые нуждались в последнем дополнительном бите. Я думаю, что это естественная прогрессия, что привычки C продолжались на C# и на других новых языках, таких как Python.

1

Я программирую на уровне приложения более низкого уровня, где ints редко превышает 100, поэтому отрицательные значения не являются проблемой (например, для i < myname.length() типа), это просто старая привычка C - и короче, чтобы печатать как уже упоминалось выше. Однако в некоторых случаях при взаимодействии с оборудованием, где я имею дело с флагами событий с устройств, uint важен в случаях, когда флаг может использовать самый старший бит.

Честно говоря, для 99,9% моей работы я мог бы легко использовать ushort, но int, знаете ли, звучит намного лучше, чем ushort.

1

Я сделал оболочку Direct3D 10 в C# & нужно использовать uint, если я хочу создать очень большие буферы вершин. Большие буферы в видеокарте не могут быть представлены с помощью подписанного int.

UINT очень полезно & глупо сказать иначе. Если кто-то думает только потому, что им никогда не нужно было использовать uint, никто другой не будет, вы ошибаетесь.

+0

Это хороший случай, когда вы можете воспользоваться более широким диапазоном. –

16

Обычно int хватает. Если вы можете удовлетворить все из следующих условий, вы можете использовать uint:

  • Это не для публичного API (с uint не CLS-совместимый).
  • Вам не нужны отрицательные числа.
  • Вам (возможно) нужен дополнительный диапазон.
  • Вы являетесь не, используя его в сравнении с < 0, как это никогда не true.
  • Вы являетесь не, используя его в сравнении с >= 0, так как это никогда не false.

Последнее требование часто забывают и познакомят ошибки:

static void Main(string[] args) 
{ 
    if (args.Length == 0) return; 
    uint last = (uint)(args.Length - 1); 

    // This will eventually throw an IndexOutOfRangeException: 
    for (uint i = last; i >= 0; i--) 
    { 
     Console.WriteLine(args[i]); 
    } 
} 
0

Некоторые языки (например,многие версии Pascal) рассматривают неподписанные типы как представляющие числовые величины; операция между неподписанным типом и подписанным типом такого же размера обычно выполняется так, как если бы операнды были переведены на следующий более крупный тип (на некоторых таких языках наибольший тип не имеет беззнакового эквивалента, поэтому такая продвижение всегда будет возможной).

Другие языки (например, C) рассматривают N-разрядные неподписанные типы как группу, которая обертывается по модулю 2^N. Обратите внимание, что вычитание N из члена такой группы не представляет собой числовое вычитание, а скорее дает член группы, который при добавлении N к нему даст исходный код. Возможно, некоторые операции, связанные с смесями подписанных и неподписанных значений, на самом деле не имеют смысла и, возможно, должны быть запрещены, но обычно будет работать даже код, который неаккуратно со своими спецификациями таких вещей, как числовые литералы, и был написан код, и неподписанные типы, и, несмотря на то, что они неаккуратные, работает, что спецификация не скоро изменится в ближайшее время.

Гораздо проще работать исключительно с подписанными типами, чем разрабатывать все тонкости взаимодействия между подписанными и неподписанными типами. Неподписанные типы полезны при разложении больших чисел из меньших частей (например, для сериализации) или для восстановления таких чисел, но в целом лучше просто использовать подписанные числа для вещей, которые фактически представляют величины

0

Я знаю, что это, вероятно, старый но я хотел дать некоторые разъяснения.

Позволяет взять int8, вы можете хранить от -128 до 127 и использовать 1 байт, что составляет в общей сложности 127 положительных чисел.
Когда вы используете int8, один из битов используется для отрицательных чисел -128.
Когда вы используете Uint8, вы указываете отрицательные числа на положительное, чтобы это позволило вам использовать 255 положительных чисел с одинаковым объемом 1 байт.
Единственный обратный путь - вы потеряли способность использовать отрицательные значения.
Другой проблемой является не все языки программирования и базы данных.
Единственная причина, по которой вы намереваетесь использовать это, на мой взгляд, - это когда вам нужно быть эффективным в программировании игр, и вам нужно хранить большие неотрицательные числа. Вот почему не многие программы используют это.

Основная причина в том, что хранение не является проблемой, и вы не можете использовать его гибко с другим программным обеспечением, плагинами, базой данных или Api. Также, например, банку понадобится отрицательный номер для хранения денег и т. Д.

Надеюсь, это поможет кому-то.

Смежные вопросы