Ich habe eine Weile beobachtet, dass C # -Programmierer dazu neigen, int überall zu verwenden und selten auf uint zurückzugreifen. Aber ich habe nie eine zufriedenstellende Antwort gefunden, warum.
Wenn Interoperabilität Ihr Ziel ist, sollte uint nicht in öffentlichen APIs angezeigt werden, da nicht alle CLI-Sprachen vorzeichenlose Ganzzahlen unterstützen. Das erklärt aber nicht, warum int selbst in internen Klassen so verbreitet ist. Ich vermute, dies ist der Grund, warum uint in der BCL sparsam verwendet wird.
Wenn Sie in C ++ eine Ganzzahl haben, für die negative Werte keinen Sinn ergeben, wählen Sie eine Ganzzahl ohne Vorzeichen.
Dies bedeutet eindeutig, dass negative Zahlen nicht zulässig sind oder erwartet werden, und der Compiler wird einige Überprüfungen für Sie durchführen. Ich vermute auch im Fall von Array-Indizes, dass die JIT die Prüfung der unteren Grenzen leicht fallen lassen kann.
Beim Mischen von Int- und Unit-Typen sind jedoch besondere Sorgfalt und Abdrücke erforderlich.
Sollte uint mehr verwendet werden? Warum?
if (i < 0 || i >= length)
mitif (unchecked((uint)i) >= length)
. Die resultierende IL hat insgesamt einen (Verzweigungs-) Befehl weniger und liefert ungefähr die gleiche Leistung (unendlich schneller). Persönlich liebe ich es einfach, weil es meinen Juckreiz gegen das Überprüfen der unteren Grenzen kratzt. Andere argumentieren wahrscheinlich aufgrund von "ungeprüft" dagegen, aber ich behaupte, dass dies eine sehr gute Linie ist, um ihre Bedeutung zu lernen, da es einfach und sofort aus dem Kontext klar ist, was der Zweck ist = hilft dem Leser zu lernen.if (unchecked((uint)i) >= unchecked((uint)length))
ergibt sich eine bessere Leistung. Dies sieht jedoch sehr kompliziert aus, und der 64-Bit-Vergleich ist immer noch leistungsfähiger als die Standardprüfung der doppelt verzweigten Grenzen bei einem 32-Bit-Build, sodass ich dies in keiner vernünftigen Situation wirklich empfehlen kann. (Ich erwähne es meistens, um darauf hinzuweisen, dass ein 64-Bit-Vergleich ansonsten verwendet wird - was für einige nützliche Informationen sein könnte.)Antworten:
uint
Ich vermute, dass Ihre Beobachtung, warum in der BCL nicht verwendet wird, der Hauptgrund ist.UInt32 ist nicht CLS-konform, was bedeutet, dass es für die Verwendung in öffentlichen APIs völlig ungeeignet ist. Wenn Sie uint in Ihrer privaten API verwenden, bedeutet dies, dass Sie Konvertierungen in andere Typen durchführen - und es ist normalerweise einfacher und sicherer, den Typ einfach gleich zu halten.
Ich vermute auch, dass dies in der C # -Entwicklung nicht so häufig vorkommt, selbst wenn C # die einzige verwendete Sprache ist, vor allem, weil es in der BCL nicht häufig vorkommt. Entwickler versuchen im Allgemeinen, (dankenswerterweise) den Stil des Frameworks nachzuahmen, auf dem sie aufbauen. In C # bedeutet dies, dass Sie versuchen, Ihre öffentlichen und internen APIs so ähnlich wie möglich der .NET Framework BCL zu machen. Dies würde bedeuten, uint sparsam zu verwenden.
quelle
int
ist kürzer zu tippen alsuint
.quelle
uint
wenn 99% der Zeit (meiner Erfahrung nach)int
ausreichen?int
, wenn ich ein Array indiziere, weil ich nie einen negativen Index haben werde. Scheint blind offensichtlich, dassuint
in diesem Fall a verwendet werden sollte.uint
sie ein wenig aufhängen.int
ist in allen Situationen, in denen Sie die Reichweite steuern, durchaus akzeptabel.for (int i = arr.Length - 1; i >= 0; i--) { }
. Wenn Sie dies mit einem Uint tun, führt dies zu einer Überlaufausnahme oder schlimmer noch zu einer Endlosschleife.Normalerweise reicht
int
es aus. Wenn Sie alle folgenden Bedingungen erfüllen können, können Sie Folgendes verwendenuint
:uint
es nicht CLS-kompatibel ist).< 0
, da dies niemals der Fall isttrue
.>= 0
, da dies niemals der Fall istfalse
.Die letzte Anforderung wird oft vergessen und führt zu Fehlern:
static void Main(string[] args) { if (args.Length == 0) return; uint last = (uint)(args.Length - 1); // This will eventually throw an IndexOutOfRangeException: for (uint i = last; i >= 0; i--) { Console.WriteLine(args[i]); } }
quelle
1) Schlechte Angewohnheit. Ernsthaft. Auch in C / C ++.
Denken Sie an das gemeinsame
for
Muster:for( int i=0; i<3; i++ ) foo(i);
Es gibt absolut keinen Grund, dort eine Ganzzahl zu verwenden. Sie werden niemals negative Werte haben. Aber fast jeder wird auf diese Weise eine einfache Schleife ausführen, selbst wenn sie (mindestens) zwei andere "Stil" -Fehler enthält.
2)
int
wird als nativer Maschinentyp wahrgenommen.quelle
Ich bevorzuge es
uint
, esint
sei denn, eine negative Zahl liegt tatsächlich im Bereich akzeptabler Werte. Insbesondere ist es einfach albern , einenint
Parameter zu akzeptieren, aber einen zu werfen,ArgumentException
wenn die Zahl kleiner als Null ist - verwenden Sie auint
!Ich bin damit einverstanden, dass dies nicht
uint
ausreichend genutzt wird, und ich ermutige alle anderen, es stärker zu nutzen.quelle
Ich programmiere auf einer untergeordneten Anwendungsebene, in der Ints selten über 100 liegen, sodass negative Werte kein Problem darstellen (z. B. für Sachen vom Typ i <myname.length ()). Es ist nur eine alte C-Gewohnheit - und kürzer zu tippen, wie oben erwähnt. In einigen Fällen ist jedoch bei der Anbindung an Hardware, bei der es sich um Ereignisflags von Geräten handelt, die Uint wichtig, wenn ein Flag möglicherweise das am weitesten links liegende (höchste) Bit verwendet.
Ehrlich gesagt, für 99,9% meiner Arbeit könnte ich leicht ushort verwenden, aber int, wissen Sie, klingt viel besser als ushort.
quelle
Ich habe einen Direct3D 10-Wrapper in C # erstellt und muss uint verwenden, wenn ich sehr große Vertex-Puffer erstellen möchte. Große Puffer in der Grafikkarte können nicht mit einem signierten Int dargestellt werden.
UINT ist sehr nützlich und es ist albern, etwas anderes zu sagen. Wenn jemand denkt, nur weil er nie gebraucht hat, wird es niemand anderes tun, dann liegen Sie falsch.
quelle
Ich denke es ist nur Faulheit. C # ist von Natur aus eine Wahl für die Entwicklung auf Desktops und anderen Computern mit relativ vielen Ressourcen.
C und C ++ haben jedoch tiefe Wurzeln in alten Systemen und eingebetteten Systemen, in denen der Speicher knapp ist. Daher werden Programmierer verwendet, um sorgfältig zu überlegen, welcher Datentyp verwendet werden soll. C # -Programmierer sind faul und da im Allgemeinen genügend Ressourcen vorhanden sind, optimiert niemand die Speichernutzung wirklich (im Allgemeinen natürlich nicht immer). Wenn ein Byte ausreichen würde, verwenden viele C # -Programmierer, einschließlich mir, der Einfachheit halber nur int. Darüber hinaus akzeptieren viele API-Funktionen Ints, sodass das Casting verhindert wird.
Ich stimme zu, dass die Auswahl des richtigen Datentyps eine gute Praxis ist, aber ich denke, die Hauptmotivation ist Faulheit.
Schließlich ist die Auswahl einer Ganzzahl mathematisch korrekter. Vorzeichenlose Ints existieren in der Mathematik nicht (nur natürliche Zahlen). Und da die meisten Programmierer einen mathematischen Hintergrund haben, ist die Verwendung einer Ganzzahl natürlicher.
quelle
Ich denke, ein großer Teil des Grundes ist, dass, als C zum ersten Mal herauskam, die meisten Beispiele der
int
Kürze halber verwendet wurden. Wir freuteninteger
uns, nicht wie bei Fortran und Pascal schreiben zu müssen , und in jenen Tagen verwendeten wir sie routinemäßig für alltägliche Dinge wie Array-Indizes und Loop-Zähler. Ganzzahlen ohne Vorzeichen waren Sonderfälle für große Zahlen, die das letzte zusätzliche Bit benötigten. Ich denke, es ist eine natürliche Entwicklung, dass C-Gewohnheiten in C # und anderen neuen Sprachen wie Python fortgesetzt wurden.quelle
Einige Sprachen (z. B. viele Versionen von Pascal) betrachten vorzeichenlose Typen als numerische Größen. Eine Operation zwischen einem vorzeichenlosen Typ und einem vorzeichenbehafteten Typ derselben Größe wird im Allgemeinen so ausgeführt, als ob die Operanden zum nächstgrößeren Typ heraufgestuft worden wären (in einigen solchen Sprachen hat der größte Typ kein vorzeichenloses Äquivalent, sodass eine solche Heraufstufung immer möglich ist ).
Andere Sprachen (z. B. C) betrachten vorzeichenlose N-Bit-Typen als eine Gruppe, die sich um Modulo 2 ^ N dreht. Beachten Sie, dass das Subtrahieren von N von einem Mitglied einer solchen Gruppe keine numerische Subtraktion darstellt, sondern das Gruppenmitglied ergibt, das, wenn N hinzugefügt wird, das Original ergibt. Bestimmte Operationen, die eine Mischung aus vorzeichenbehafteten und vorzeichenlosen Werten beinhalten, sind wahrscheinlich nicht wirklich sinnvoll und hätten vielleicht verboten werden sollen, aber selbst Code, der mit seinen Spezifikationen für Dinge wie numerische Literale schlampig ist, funktioniert normalerweise, und es wurde Code geschrieben, der vorzeichenbehaftete Werte mischt und vorzeichenlose Typen und obwohl sie schlampig sind, funktionieren sie, so dass sich die Spezifikation nicht so schnell ändern kann.
Es ist viel einfacher, ausschließlich mit signierten Typen zu arbeiten, als alle Feinheiten der Interaktion zwischen signierten und nicht signierten Typen zu ermitteln. Vorzeichenlose Typen sind nützlich, wenn Sie große Zahlen aus kleineren Teilen zerlegen (z. B. zur Serialisierung) oder solche Zahlen wiederherstellen möchten. Im Allgemeinen ist es jedoch besser, einfach vorzeichenbehaftete Zahlen für Dinge zu verwenden, die tatsächlich Mengen darstellen
quelle
Ich weiß, dass dies wahrscheinlich ein alter Thread ist, aber ich wollte etwas Klarheit geben.
Nehmen wir ein int8, das Sie zwischen –128 und 127 speichern können, und es verwendet 1 Byte, was insgesamt 127 positiven Zahlen entspricht.
Wenn Sie ein int8 verwenden, wird eines der Bits für die negativen Zahlen -128 verwendet.
Wenn Sie ein Uint8 verwenden, geben Sie die negativen Zahlen an die positiven an, sodass Sie 255 positive Zahlen mit der gleichen Speichermenge von 1 Byte verwenden können.
Der einzige Nachteil ist, dass Sie jetzt nicht mehr in der Lage sind, negative Werte zu verwenden.
Ein weiteres Problem dabei ist, dass nicht alle Programmiersprachen und Datenbanken dies unterstützen.
Der einzige Grund, warum Sie dies meiner Meinung nach verwenden würden, ist, wenn Sie effizient in der Gaming-Programmierung sein müssen und große, nicht negative Zahlen speichern müssen. Dies ist der Grund, warum nicht viele Programme dies verwenden.
Der Hauptgrund ist, dass Speicher kein Problem darstellt und Sie ihn nicht flexibel mit anderer Software, Plugins, Datenbanken oder APIs verwenden können. Auch zum Beispiel würde eine Bank negative Zahlen benötigen, um Geld usw. zu speichern.
Ich hoffe das wird jemandem helfen.
quelle