2010-06-22 20 views
75

ho osservato per un po 'che C# programmatori tendono ad usare int ovunque, e raramente ricorrere a uint. Ma non ho mai trovato una risposta soddisfacente al perché.utilizzando uint vs int

Se l'interoperabilità è il vostro obiettivo, uint non dovrebbe apparire in API pubbliche, perché non tutte le lingue CLI supportano interi senza segno. Ma questo non spiega perché int sia così diffuso, anche nelle classi interne. Sospetto che questo sia il motivo per cui uint viene usato con parsimonia nel BCL.

In C++, se si dispone di un numero intero per il quale i valori negativi non hanno alcun senso, si sceglie un intero senza segno.

Ciò significa chiaramente che i numeri negativi non sono consentiti o previsti e il compilatore eseguirà alcuni controlli. Sospetto anche nel caso degli indici di array, che il JIT possa facilmente abbandonare il controllo dei limiti inferiori.

Tuttavia, quando si mescolano i tipi int e unità, saranno necessari ulteriore assistenza e trasmissioni.

caso uint essere utilizzato di più? Perché?

+0

http://stackoverflow.com/questions/6301/why-is-array-length-an-int-and-not-an-uint – drharris

+0

Appena ho avuto un deja vu: D, quasi esatta la stessa domanda è stato chiesto poco fa. – KroaX

+0

Come per i controlli dei limiti inferiori (nel caso sia necessario scriverne uno proprio) è possibile sostituire 'if (i < 0 || i > = length)' con 'if (deselezionato ((uint) i)> = length)'. L'IL risultante avrà un'istruzione (derivata) in meno in totale e darà approssimativamente le stesse prestazioni (infinitamente più veloce). Personalmente lo amo semplicemente perché mi graffia il prurito contro il controllo dei limiti inferiori. È probabile che altri si discuteranno a causa di "incontrollato", ma io sostengo che questa è una buona linea per imparare il suo significato perché è semplice e immediatamente libera dal contesto qual è lo scopo = aiuta il lettore ad imparare. – AnorZaken

risposta

47

tua osservazione del perché uint non viene utilizzato nel BCL è la ragione principale, ho il sospetto.

UInt32 non è compatibile con CLS, il che significa che è del tutto inadatto per l'uso in API pubbliche. Se utilizzerai uint nella tua API privata, ciò comporterà conversioni con altri tipi, ed è in genere più semplice e sicuro mantenere semplicemente il tipo.

Ho anche il sospetto che questo non è così comune in C# di sviluppo, anche se C# è l'unica lingua in uso, soprattutto perché non è comune nel BCL. Gli sviluppatori, in generale, cercano di (per fortuna) imitare lo stile del quadro su cui stanno costruendo - nel caso in cui C# 's, questo significa cercare di rendere il vostro API, pubbliche e interne, appaiono tanto come il .NET Framework BCL possibile. Ciò significherebbe usare uint con parsimonia.

+0

http://stackoverflow.com/questions/2013116/should-i-use-uint-in-c-for-values-that-cant-be-negative è una domanda che si occupa di un argomento simile – Stephan

71

int è più corto da digitare rispetto uint.

+2

Sospetto che sia abbastanza vicino alla verità. Perché usare 'uint' quando il 99% delle volte (nella mia esperienza)' int' sarà sufficiente? –

+0

Sì, non ho mai avuto un motivo per usare un 'uint'. E, se ho bisogno di memorizzare un numero più grande, uso solo un 'long'. È bello poter usare -1 come errore o valore predefinito. – jjnguy

+12

@Justin: "I numeri magici" come -1 non sono una buona idea, in generale. Passare a lungo significa utilizzare la memoria 2x senza motivo, inoltre ... "unità" è sicuramente utile, a patto che non sia necessario interagire con altre API. –

4

Preferisco uint a int a meno che un numero negativo sia effettivamente nell'intervallo di valori accettabili. In particolare, l'accettazione di un int param ma lanciando un ArgumentException se il numero è inferiore a zero è solo stupido - usare un uint!

Sono d'accordo che uint è attualmente sottoutilizzato, e incoraggio tutti gli altri di usarlo di più.

+7

È molto pericoloso accettare solo uint e non controllare i limiti. Se qualcuno passa un valore negativo, il CLR lo interpreterà come int grande, ovvero per -1 ottieni uint.maxvalue. Questo non è un comportamento desiderato. – Henri

+18

@Henri: C# non ha una conversione implicita da int a uint, quindi non c'è "Se qualcuno passa un valore negativo". Ovviamente un controllo dei limiti sul limite superiore è ancora appropriato (ma ora hai solo bisogno di un controllo invece di due). –

0

penso che sia solo pigrizia. C# è intrinsecamente una scelta per lo sviluppo su desktop e altre macchine con relativamente molte risorse.

C e C++, tuttavia, ha profonde radici in vecchi sistemi e sistemi embedded in cui la memoria è scarsa, quindi i programmatori sono utilizzati per riflettere attentamente quale tipo di dati da utilizzare. I programmatori C# sono pigri e, dato che ci sono abbastanza risorse in generale, nessuno ottimizza realmente l'utilizzo della memoria (in generale, non sempre, ovviamente). Evento se un byte sarebbe sufficiente, molti programmatori C#, incluso me, usano semplicemente int per semplicità. Inoltre, molte funzioni API accettano int, quindi impedisce il casting.

Concordo sul fatto che la scelta del tipo di dati corretto sia una buona pratica, ma penso che la motivazione principale sia la pigrizia.

Infine, la scelta di un numero intero è più corretta dal punto di vista matematico.Inte unsigned non esistono in matematica (solo numeri naturali). E poiché la maggior parte dei programmatori ha uno sfondo matematico, l'utilizzo di un numero intero è più naturale.

+0

Non direi che è pigrizia, anche se la pigrizia ha i suoi meriti. È più che altro la maggior parte delle volte, non mi interessa abbastanza della cosa intintura, sprecare i miei cicli cerebrali su una tale decisione, e basta andare con l'int. L'hardware è a posto, i programmatori possono essere costosi. – SWeko

+0

I programmatori sono pigri. Questa è una brutta cosa Raymond direbbe che i programmatori odiano pagare le loro tasse! – Wizard79

+0

Sarei il primo ad amministrare che noi programmatori C# siamo pigri ma non è necessariamente una cosa negativa. – ChaosPandion

12

1) Cattiva abitudine. Sul serio. Anche in C/C++.

Pensate al comune for modello:

for(int i=0; i<3; i++) 
    foo(i); 

Non c'è assolutamente alcuna ragione per utilizzare un intero lì. Non avrai mai valori negativi. Ma quasi tutti faranno un ciclo semplice in questo modo, anche se contiene (almeno) altri due errori di "stile".

2) int viene percepito come il tipo nativo della macchina.

0

Penso che una buona parte del motivo sia che quando C è uscito per la maggior parte degli esempi ha usato int per brevità. Ci siamo rallegrati di non dover scrivere integer come abbiamo fatto con Fortran e Pascal, e in quei giorni li usavamo abitualmente per cose banali come indici di array e contatori di loop. Gli interi senza segno erano casi speciali per numeri grandi che avevano bisogno dell'ultimo bit in più. Penso che sia una progressione naturale che le abitudini di C siano continuate in C# e in altri nuovi linguaggi come Python.

1

I programma a un livello di applicazione di livello inferiore in cui raramente gli inte sono superiori a 100, quindi i valori negativi non sono un problema (ad esempio per i tipi di materiale I < myname.length()) è solo una vecchia abitudine C - e più breve da digitare come menzionato sopra. Tuttavia, in alcuni casi, quando si interfaccia con l'hardware in cui mi occupo di flag di eventi dai dispositivi, l'uint è importante nei casi in cui un flag può utilizzare il bit più a sinistra (il più alto).

Onestamente, per il 99,9% del mio lavoro potrei usare facilmente ushort, ma int, sai, i suoni suona molto meglio di ushort.

1

Ho creato un wrapper Direct3D 10 in C# & necessario utilizzare uint se si desidera creare buffer di vertice molto grandi. I grandi buffer nella scheda video non possono essere rappresentati con un int firmato.

UINT è molto utile & è sciocco dire altrimenti. Se qualcuno pensa solo perché non hanno mai avuto bisogno di usare uint nessun altro lo farà, ti sbagli.

+0

Questo è un buon caso in cui puoi sfruttare la gamma più ampia. –

16

Normalmente int è sufficiente. Se si riesce a soddisfare tutte le seguenti condizioni, è possibile utilizzare uint:

  • Non è per un'API pubblica (dal uint non è compatibile con CLS).
  • Non sono necessari numeri negativi.
  • È possibile che sia necessario il campo aggiuntivo.
  • Siete non utilizzandolo in un confronto con < 0, poiché non è mai true.
  • Sei non di utilizzarlo in un confronto con >= 0, come che non è mai false.

L'ultimo requisito viene spesso dimenticato e introdurrà bug:

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]); 
    } 
} 
0

Alcune lingue (per esempiomolte versioni di Pascal) considerano i tipi non firmati come rappresentativi di quantità numeriche; una operazione tra un tipo non firmato e un tipo firmato della stessa dimensione verrà generalmente eseguita come se gli operandi fossero promossi al tipo successivo più grande (in alcune di queste lingue, il tipo più grande non ha un equivalente non firmato, quindi tale promozione sarà sempre possibile).

Altre lingue (ad esempio C) riguarda N-bit senza segno tipi come gruppo che avvolge modulo 2^N. Si noti che la sottrazione di N da un membro di un tale gruppo non rappresenta la sottrazione numerica, ma piuttosto il membro del gruppo che, quando N viene aggiunto ad esso, produrrebbe l'originale. Probabilmente, alcune operazioni che comportano miscele di valori firmati e non firmati non hanno realmente senso e forse dovrebbero essere vietate, ma anche il codice che è sciatto con le sue specifiche di cose come i letterali numerici di solito funzionerà, e il codice è stato scritto che mescola i segni e tipi non firmati e, nonostante sia sciatto, funziona, che le specifiche non sono suscettibili di cambiare presto.

È molto più facile lavorare esclusivamente con i tipi firmati piuttosto che elaborare tutte le complessità delle interazioni tra tipi firmati e non firmati. I tipi non firmati sono utili quando si decodificano grandi numeri di pezzi più piccoli (ad esempio per la serializzazione) o per ricostituire tali numeri, ma in generale è meglio usare semplicemente i numeri firmati per cose che rappresentano effettivamente quantità

0

So che questo è probabilmente un vecchio filo ma volevo dare qualche chiarimento.

consente di dare un int8 è possibile memorizzare -128 a 127 e utilizza 1 byte che è un totale di 127 numeri positivi.
Quando si utilizza un int8, uno dei bit viene utilizzato per i numeri negativi -128.
Quando si utilizza un Uint8 si assegnano i numeri negativi al positivo, in questo modo è possibile utilizzare 255 numeri positivi con la stessa quantità di memoria di 1 byte.
L'unico inconveniente è che hai perso la possibilità di utilizzare valori negativi.
Un altro problema con questo non è tutti i linguaggi di programmazione e database supportano questo.
L'unico motivo per cui dovresti usare questo a mio parere è quando devi essere efficiente come la programmazione di giochi e devi memorizzare numeri non negativi di grandi dimensioni. Ecco perché non molti programmi lo usano.

La ragione principale è di archiviazione non è un problema e non lo si può utilizzare in modo flessibile con altri software, plug-in, database, o API. Anche per esempio una banca avrebbe bisogno di numeri negativi per immagazzinare soldi, ecc.

Spero che questo aiuti qualcuno.