Используйте Uint или Int - PullRequest
       79

Используйте Uint или Int

10 голосов
/ 26 сентября 2011

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

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

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

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

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

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

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

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

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

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

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

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

Питер

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

Ответы [ 5 ]

5 голосов
/ 26 сентября 2011

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

Использование 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, он действителен.

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

3 голосов
/ 26 сентября 2011

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

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

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

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

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

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

2 голосов
/ 26 сентября 2011

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

1 голос
/ 26 сентября 2011

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

Интересное чтение - ТАК ссылка

1 голос
/ 26 сентября 2011

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

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

это компромисс для скорости противробастности.

...