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


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

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

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

P. S.: Я видел этот вопрос, и это по крайней мере объясняет, почему сам каркас всегда использует int но даже в собственном коде это на самом деле громоздкие придерживаться uint Что делает меня думаю, что это, по-видимому, не очень хотел.

8 67

8 ответов:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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