Должен ли я использовать uint в С# для значений, которые не могут быть отрицательными?

Я только что попробовал реализовать класс, где многочисленные свойства length/count и т.д. uint вместо int. Однако, делая это, я заметил, что на самом деле это больно, как будто никто на самом деле этого не хочет.

Почти все, что выделяет интегральный тип, возвращает int, поэтому требует отбрасывания в нескольких точках. Я хотел построить StringBuffer с его длиной буфера по умолчанию для одного из полей этого класса. Требуется также бросок.

Итак, я подумал, нужно ли мне просто вернуться к int здесь. В любом случае, я не использую весь диапазон. Я просто подумал, что то, с чем я имею дело, просто не может быть отрицательным (если бы это было так, это была бы ошибка), было бы неплохой идеей использовать uint.

PS: я видел этот вопрос, и это по крайней мере объясняет, почему сама фреймворк всегда использует int, но даже в собственном коде на самом деле громоздко придерживаться uint, что заставляет меня думать, что это, по-видимому, действительно не требуется.

Ответ 1

В то время как строго вам следует использовать uint для переменных, которые содержат неотрицательное целое число, вы столкнулись с одной из причин, почему это не всегда практически возможно.

В этом случае я не думаю, что снижение удобочитаемости, которое приходит с необходимостью делать броски, стоит того.

Ответ 2

Я добавлю к другим ответам также, что использование uint как типа публичного поля, свойства, метода, параметра и т.д. является нарушением правил Common Language Specification и, по возможности, следует избегать.

Ответ 3

Отрицательное значение часто используется для сигнализации об ошибке, и размер операции часто возвращается вызовом функции; отрицательное значение может, следовательно, сигнализировать об ошибке, не прибегая к механизму исключения.

Также обратите внимание, что .NET часто основывается на прямых библиотеках C, поэтому разумно продолжить это соглашение. Если вам требуется большее пространство индекса, вы можете нарушить соглашение для разных механизмов сигнализации об ошибках.

Ответ 4

Мое личное чувство заключается в том, что вы, вероятно, должны просто придерживаться int. Не стоит добавлять приведение к почти каждому доступу к ресурсу только для того, чтобы вернуть числовой диапазон, который .NET вряд ли позволит вам использовать в любом случае.

Ответ 5

Использование int также полезно для обнаружения переполнения целых чисел в операциях.

Ответ 6

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

if (len < 0)
    terminate_program("length attained impossible value.");

Конечно, ваши программы не должны просчитывать что-либо для начала, но я считаю, что они также должны быть написаны для быстрого обнаружения числовых эров без распространения. В случае, когда MaxValue 2 ^ 31 достаточно, я говорю использовать int вместе с правильным использованием System.Diagnostics.Debug.Assert() и соответствующими проверками ошибок, как показано выше.

Если вы используете uint, используйте его вместе с checked, чтобы предотвратить переполнение и получить те же результаты. Однако я обнаружил, что проверка немного сложна для применения к существующему коду, который использует касты для какой-либо цели.

Ответ 7

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

using System.Diagnostics;
...
Debug.Assert (i > 0);

Ответ 8

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

Если вы боитесь, что можете переполнить int, то там обязательно, но не досрочно оптимизируйте.

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