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

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

я заметил, что в .NET public classes свойство называется Length всегда использует целые числа со знаком.

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

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

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

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

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

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

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

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

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

Петр

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

5 ответов


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

использовать uint. Платформа не делает, потому что она не совместима с CLS. Но вы должны быть CLS-совместимыми? (Есть также некоторые не-удовольствие проблемы с арифметикой, которые возникают, это не весело, чтобы бросить все на месте. Я, как правило, недействительными 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 в вашей модели домена и инкапсулировать все концепции, которые приходят с ней.


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

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

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

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

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

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


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


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

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

его обмен на скорость против надежности.


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

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

интересно читать-так ссылка