2008-08-08 15 views
77

Dlaczego jest Array.Length int, a nie uint. To mi przeszkadza (tylko trochę), ponieważ wartość długości nigdy nie może być ujemna.Dlaczego Array.Length int, a nie uint

To także zmuszony mnie do używania int dla długości nieruchomości na własnej klasie, bo gdy określić int wartość, to musi być wrzuconym wyraźnie ...

Więc pytanie jest ostateczna : czy jest jakiś sposób użycia dla unsigned int (uint)? Nawet Microsoft wydaje się ich nie używać.

+0

Pomimo problemów podnoszonych poniżej, myślę, że powinien on zmienić się na UInt. – alan2here

+1

@ alan2Podczas takiej zmiany złamałbym prawie cały kod, więc nie stanie się tak, jeśli mnie zapytasz! – Peter

Odpowiedz

0

Zazwyczaj wartości całkowite są podpisywane, chyba że wyraźnie potrzebujesz niepodpisanej wartości. To po prostu sposób, w jaki są używane. Być może nie zgadzam się z tym wyborem, ale tak właśnie jest.

Na razie, przy dzisiejszych typowych ograniczeniach pamięci, jeśli macierz lub podobna struktura danych wymaga długości UInt32, należy wziąć pod uwagę inne struktury danych.

z tablicy bajtów, Int32 daje 2GB wartości

+13

"ale tak po prostu jest." - Nie, rzeczy nigdy nie są takie, jakimi są. Zawsze podejmowana jest decyzja projektowa i zawsze warto zapytać dlaczego. Można nauczyć się czegoś od plusów i minusów lub angażować projektanta (w niektórych przypadkach) w dyskusję o nich. Zawsze zadawaj pytania! :) –

1

Myślę, że może to również mieć związek z upraszczaniem rzeczy na niższym poziomie, ponieważ Array.Length będzie oczywiście dodana do liczby ujemnej w pewnym momencie, jeśli Array.Length były niepodpisane i dodane do ujemnej int (dwójki uzupełnienie), mogą pojawić się niechlujne wyniki.

+0

Podaj przykład? 'uint lenght = 3; int x = -4; Console.WriteLine (x + długość);' daje -1 dobrze. –

1

Wygląda na to, że nikt nie dostarczył odpowiedzi na "ostateczne pytanie".

Uważam, że podstawowym zastosowaniem niepodpisanych int jest zapewnienie łatwiejszego połączenia z systemami zewnętrznymi (P/Invoke i tym podobne) oraz pokrycie potrzeb różnych języków przenoszonych do .NET.

+0

Niepodpisane typy są niezbędne przy łączeniu wielu mniejszych wartości w celu utworzenia większego. Można połączyć dwa UInt16, aby utworzyć UInt32, obliczając '(HighPart << 16) + LowPart', i można podzielić UInt32 na dwa UInt16 za pośrednictwem' (Uint16) (Wartość >> 16) 'i' (Uint16) (Wartość & 65535) '. Takie operacje byłyby bardzo niewygodne, gdyby 'LowPart' musiał być podpisanym typem. To powiedziawszy, interakcje między podpisanymi i niepodpisanymi typami są często mylące i problematyczne. Niepodpisane typy należy pod wieloma względami uważać za swój własny świat. – supercat

45

Wiele powodów:

  • uint nie jest zgodny z CLS, dzięki czemu wbudowany typu (array) zależny od niego byłby problematyczny
  • Środowisko wykonawcze jak pierwotnie zaprojektowany zakazuje obiekt na stercie zajmującej więcej niż 2 GB pamięci. Ponieważ maksymalna wielkość tablicy, która byłaby mniejsza lub równa temu limitowi, byłaby nowym bajtem [int.MaxValue], byłoby zastanawiające dla ludzi, aby móc generować dodatnie, ale nielegalne długości tablic.
  • Historycznie C# dziedziczy wiele ze swojej składni i konwencji od C i C++.W tych tablicach są po prostu arytmetyczne wskaźniki, więc możliwe było negatywne indeksowanie tablic (choć normalnie nielegalne i niebezpieczne). Ponieważ wiele istniejących kodów zakłada, że ​​indeks tablicy jest podpisany, byłby to współczynnik
  • W powiązanej notatce użycie liczby całkowitej ze znakiem dla indeksów tablic w C/C++ oznacza, że ​​współdziałanie z tymi językami i niezarządzanymi funkcjami wymagałoby użycia w tych okolicznościach, co może wprowadzić w błąd ze względu na niespójność.
  • Implementacja BinarySearch (bardzo przydatny składnik wielu algorytmów) polega na wykorzystaniu ujemnego zakresu int do wskazania, że ​​wartość nie została znaleziona i Lokalizacja, w której taka wartość powinna zostać wstawiona w celu zachowania sortowanie.
  • Podczas pracy z tablicą jest prawdopodobne, że użytkownik chciałby uzyskać ujemne przesunięcie istniejącego indeksu. Jeśli użyłeś przesunięcia, które poprowadziłoby Cię przez początek tablicy za pomocą jednostki, zachowanie zawijające sprawiłoby, że twój indeks byłby legalny (w tym sensie, że jest dodatni). Z int wynik byłby nielegalny (ale bezpieczny, ponieważ środowisko uruchomieniowe chroni przed odczytaniem nieprawidłowej pamięci)
+2

Jeśli nic na stercie nie może przekraczać 2 Gb, to prawie wszystkie tablice o długości int.MaxValue są niedozwolone, ponieważ większość typów jest większa niż 1 bajt. – ScottS

+0

istotnie, ale ((uint) (int.MaxValue)) + 1 byłby zagwarantowany źle dla * niczego *. int jest daleki od ideału, ale równowaga rzeczy sprawia, że ​​legalnie pozostajemy z int jako typem. – ShuggyCoUk

+0

Zaczynając od tego, że jest to typ ArrayIndex (w zasadzie size_t), który w czysty i bezpieczny sposób przetłumaczyłby się na int, być może ułatwiłoby to w przyszłości korzystanie z tablic 2 GB w przyszłości przy mniejszym bólu. Ale pragmatyka mówi, że java ma ten sam problem, więc dlaczego podjąć ryzyko? – ShuggyCoUk

Powiązane problemy