Использовать uint или int

Определенно, я знаю основные различия между целыми числами без знака (uint) и целыми числами со знаком (int).

Я заметил, что в общедоступных классах .NET свойство с именем Length всегда использует целые числа со знаком.

Возможно, это потому, что целые числа без знака не совместимы с CLS.

Однако, например, в моей статической функции:

public static double GetDistributionDispersion(int tokens, int[] positions)

Параметр tokens и все элементы в positions не могут быть отрицательными. Если это отрицательно, конечный результат бесполезен. Поэтому, если я использую int как для tokens, так и positions, я должен проверять значения каждый раз, когда вызывается эта функция (и возвращать нечувствительные значения или бросать исключения, если найдены отрицательные значения???), что утомительно.

ОК, тогда мы должны использовать uint для обоих параметров. Это действительно имеет смысл для меня.

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

Итак, одним словом, что мне делать?

Я мог бы предоставить два случая:

  • Эта функция будет вызвана только мной в моем собственном решении;
  • Эта функция будет использоваться в качестве библиотеки другими в другой команде.

Должны ли мы использовать разные схемы для этих двух случаев?

Петр

P.S.: Я сделал много исследований, и по-прежнему нет причин убеждать меня не использовать uint: -)

Ответ 1

Я вижу три варианта.

Используйте uint. Структура не потому, что она не соответствует CLS. Но вы должны быть совместимы с CLS? (Есть также некоторые не-забавные проблемы с арифметикой, которые возникают, и это не забавно бросать по всему месту. Я склоняюсь к void uint по этой причине).

Используйте int, но используйте контракты:

Contract.Requires(tokens >= 0);
Contract.Requires(Contract.ForAll(positions, position => position >= 0));

Сделать это в явном виде именно тем, что вам нужно.

Создайте настраиваемый тип, который инкапсулирует требование:

struct Foo {
    public readonly int foo;

    public Foo(int foo) {
        Contract.Requires(foo >= 0);
        this.foo = foo;
    }

    public static implicit operator int(Foo foo) {
        return this.foo;
    }

    public static explicit operator Foo(int foo) {
        return new Foo(foo);
    }
}

Тогда:

public static double GetDistributionDispersion(Foo tokens, Foo[] positions) { }

А, хорошо. Мы не должны беспокоиться об этом в нашем методе. Если мы получаем Foo, это действительно.

У вас есть причина требовать неотрицательности в вашем домене. Он моделирует некоторую концепцию. Мог бы также продвинуть эту концепцию к объекту bonafide в вашей модели домена и инкапсулировать все концепции, которые приходят с ним.

Ответ 2

Да за int. Однажды я попытался найти себе все, чтобы реорганизовать все снова, как только у меня была доля досадных бросков в моей библиотеке. Я предполагаю, что решение перейти на int по историческим причинам, где часто результат -1 указывает на некоторую ошибку (например, в IndexOf).

Ответ 3

Я использую uint.

Да, другие ответы правильны... Но я предпочитаю тогда uint по одной причине:

Сделать интерфейс более понятным. Если параметр (или возвращаемое значение) не имеет знака, это потому, что он не может быть отрицательным (вы видели отрицательный подсчет коллекции?). В противном случае мне нужно проверить параметры, параметры документа (и возвращаемое значение), которые не могут быть отрицательными; то мне нужно написать дополнительные модульные тесты для проверки параметров и возвращенных значений (ничего себе, и кто-то будет жаловаться на выполнение бросков? Являются ли тактильные линки? Нет, по моему опыту).

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

Я не возражаю против CLS compliace, так почему я должен быть? С моей точки зрения, вопрос следует обратить вспять: почему я должен использовать ints, когда значение не может быть отрицательным?

В случае возврата отрицательного значения для дополнительной информации (ошибки, например...): Мне не нравится дизайн C-ish. Я думаю, что для этого может быть более современный дизайн (например, использование исключений или альтернативное использование значений и возвращаемых значений).

Ответ 4

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

Значения

также становятся отрицательными при переполнении, утверждение будет ловить его.

его компромисс для скорости и надежности.

Ответ 5

Как вы читаете, это нарушает правила Common Language Specification, но как часто эта функция будет использоваться, и в случае, если она будет запутана другим способом, ее нормальным для них ожидать int в качестве параметра, который заставит вас в проблему литья значений.

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

Интересная ссылка Read-SO