Какое-то время я заметил, что программисты на C # обычно везде используют int и редко прибегают к uint. Но я так и не нашел удовлетворительного ответа на вопрос, почему.
Если ваша цель - совместимость, uint не должен появляться в общедоступных API, потому что не все языки интерфейса командной строки поддерживают целые числа без знака. Но это не объясняет, почему int настолько распространен даже во внутренних классах. Я подозреваю, что это причина того, что uint экономно используется в BCL.
В C ++, если у вас есть целое число, для которого отрицательные значения не имеют смысла, вы выбираете целое число без знака.
Это явно означает, что отрицательные числа недопустимы и не ожидаются, и компилятор выполнит некоторую проверку за вас. Я также подозреваю, что в случае индексов массива JIT может легко отказаться от проверки нижних границ.
Однако при смешивании типов int и unit потребуется дополнительная осторожность и приведение типов.
Следует ли использовать uint больше? Почему?
if (i < 0 || i >= length)
наif (unchecked((uint)i) >= length)
. Итоговый IL будет иметь на одну инструкцию (ветвление) меньше всего и даст примерно такую же производительность (бесконечно быстрее). Лично мне он нравится просто потому, что он чешет меня от проверки нижних границ. Другие, вероятно, будут возражать против этого из-за «непроверенного», но я утверждаю, что это очень хорошая строка для изучения ее значения, потому что она проста и мгновенно ясно из контекста, какова цель = помогает читателю учиться.if (unchecked((uint)i) >= unchecked((uint)length))
дает лучшую производительность. Однако это выглядит очень запутанным, и 64-битное сравнение по-прежнему более производительно, чем стандартная проверка границ с двойным ветвлением на 32-битной сборке, поэтому я не могу рекомендовать это в любой разумной ситуации. (Я в основном упоминаю об этом, чтобы указать, что в противном случае используется 64-битное сравнение, что может быть полезно для некоторых.)Ответы:
uint
Я подозреваю, что ваше наблюдение о том, почему не используется в BCL, является основной причиной.UInt32 не соответствует требованиям CLS, что означает, что он полностью не подходит для использования в общедоступных API. Если вы собираетесь использовать uint в своем частном API, это будет означать преобразование в другие типы - и обычно проще и безопаснее просто сохранить тот же тип.
Я также подозреваю, что это не так часто встречается при разработке на C #, даже когда C # является единственным используемым языком, в первую очередь потому, что он не распространен в BCL. Разработчики в целом стараются (к счастью) имитировать стиль фреймворка, на котором они строят - в случае C # это означает попытку сделать ваши API, общедоступные и внутренние, максимально похожими на BCL .NET Framework. Это означало бы экономное использование uint.
источник
int
короче набрать чемuint
.источник
uint
когда в 99% случаев (по моему опыту)int
будет достаточно?int
для индексации массива, потому что у меня никогда не будет отрицательного индекса. Кажется совершенно очевидным, чтоuint
в этом случае следует использовать a .uint
может немного повредить им.int
вполне приемлемо для использования во всех ситуациях, когда вы контролируете дальность действия.for (int i = arr.Length - 1; i >= 0; i--) { }
. Выполнение этого с помощью uint приведет к исключению переполнения или, что еще хуже, к бесконечному циклу.Обычно
int
хватит. Если вы можете удовлетворить все следующие условия, вы можете использоватьuint
: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]); } }
источник
1) Вредная привычка. Шутки в сторону. Даже в C / C ++.
Подумайте об общем
for
образце:for( int i=0; i<3; i++ ) foo(i);
Нет абсолютно никаких причин использовать здесь целое число. У вас никогда не будет отрицательных значений. Но почти каждый будет выполнять простой цикл таким образом, даже если он содержит (по крайней мере) две другие «стилистические» ошибки.
2)
int
воспринимается как родной тип машины.источник
Я предпочитаю ,
uint
чтобы ,int
если отрицательное число не является на самом деле в пределах допустимых значений. В частности, приниматьint
параметр, но бросать,ArgumentException
если число меньше нуля, просто глупо - используйтеuint
!Я согласен с тем, что
uint
он недостаточно используется, и призываю всех использовать его чаще.источник
Я программирую на более низком уровне приложения, где int редко превышают 100, поэтому отрицательные значения не являются проблемой (например, для материала типа i <myname.length ()), это просто старая привычка C - и короче для ввода, как упоминалось выше. Однако в некоторых случаях при взаимодействии с оборудованием, где я имею дело с флагами событий от устройств, uint важен в случаях, когда флаг может использовать самый левый (самый высокий) бит.
Честно говоря, для 99,9% своей работы я мог легко использовать ushort, но int, знаете ли, звучит намного лучше, чем ushort.
источник
Я создал оболочку Direct3D 10 на C #, и мне нужно использовать uint, если я хочу создавать очень большие буферы вершин. Большие буферы на видеокарте не могут быть представлены подписанным int.
UINT очень полезен, и глупо говорить иначе. Если кто-то думает только потому, что им никогда не нужно было использовать uint, никто другой не будет, то вы ошибаетесь.
источник
Я думаю, это просто лень. C # по сути является выбором для разработки на настольных компьютерах и других машинах с относительно большими ресурсами.
C и C ++, однако, имеют глубокие корни в старых системах и встроенных системах, где память невелика, поэтому программисты привыкли тщательно продумывать, какой тип данных использовать. Программисты на C # ленивы, и, поскольку ресурсов в целом достаточно, никто особо не оптимизирует использование памяти (в общем, не всегда, конечно). Событие, если байта будет достаточно, многие программисты C #, включая меня, просто используют int для простоты. Более того, многие функции API принимают целые числа, что предотвращает приведение типов.
Я согласен с тем, что выбор правильного типа данных - это хорошая практика, но я думаю, что основная мотивация - это лень.
Наконец, выбор целого числа более математически правильный. Беззнаковые целые числа не существуют в математике (только натуральные числа). А поскольку большинство программистов имеют математическое образование, использование целых чисел более естественно.
источник
Я думаю, что во многом причина в том, что, когда впервые появился C, большинство примеров использовалось
int
для краткости. Мы радовались тому,integer
что нам не нужно писать, как мы это делали с Фортраном и Паскалем, и в те дни мы обычно использовали их для таких повседневных вещей, как индексы массивов и счетчики циклов. Целые числа без знака были особым случаем для больших чисел, которым требовался последний дополнительный бит. Я думаю, что это естественный прогресс, когда привычки C продолжились в C # и других новых языках, таких как Python.источник
Некоторые языки (например, многие версии Паскаля) рассматривают беззнаковые типы как представление числовых величин; операция между беззнаковым типом и подписанным типом того же размера обычно выполняется так, как если бы операнды были переведены в следующий больший тип (в некоторых таких языках самый большой тип не имеет эквивалента без знака, поэтому такое продвижение всегда будет возможно ).
Другие языки (например, C) рассматривают N-битные беззнаковые типы как группу, которая оборачивается по модулю 2 ^ N. Обратите внимание, что вычитание N из члена такой группы не представляет собой числовое вычитание, а скорее дает член группы, который, когда к нему добавляется N, дает оригинал. Возможно, определенные операции, включающие смесь значений со знаком и без знака, на самом деле не имеют смысла и, возможно, должны были быть запрещены, но даже код, который неаккуратен со своими спецификациями таких вещей, как числовые литералы, обычно будет работать, и был написан код, который смешивает знаковые и беззнаковые типы, и, несмотря на то, что они небрежны, действительно работает, так что спецификация не будет меняться в ближайшее время.
Намного проще работать исключительно со знаковыми типами, чем разбираться во всех тонкостях взаимодействия между знаковыми и неподписанными типами. Типы без знака полезны при разложении больших чисел на более мелкие части (например, для сериализации) или для восстановления таких чисел, но в целом лучше просто использовать числа со знаком для вещей, которые фактически представляют количества
источник
Я знаю, что это, вероятно, старая ветка, но я хотел дать некоторые пояснения.
Возьмем int8, в котором вы можете хранить от –128 до 127, и он использует 1 байт, который в сумме составляет 127 положительных чисел.
Когда вы используете int8, один из битов используется для отрицательных чисел -128.
Когда вы используете Uint8, вы присваиваете отрицательные числа положительным, так что это позволяет вам использовать 255 положительных чисел с тем же объемом памяти 1 байт.
Единственный недостаток - это то, что вы потеряли возможность использовать отрицательные значения.
Другая проблема заключается в том, что не все языки программирования и базы данных поддерживают это.
На мой взгляд, единственная причина, по которой вы могли бы использовать это, - это когда вам нужно быть эффективным в программировании, например, в играх, и вам нужно хранить большие неотрицательные числа. Вот почему не многие программы используют его.
Основная причина в том, что хранилище не является проблемой, и вы не можете гибко использовать его с другим программным обеспечением, плагинами, базами данных или API. Также, например, банку потребуются отрицательные числа для хранения денег и т. Д.
Надеюсь, это кому-то поможет.
источник