Quali sono i casi in cui i tipi di dati 'uint' e 'short' sono più adatti rispetto allo standard int (32)?

21

Capisco le differenze di capacità e valori che possono rappresentare, ma sembra che le persone sempre usino Int32 indipendentemente dal fatto che sia appropriato. Nessuno sembra mai utilizzare la versione senza firma ( uint ) anche se molto spesso si adatta meglio in quanto descrive un valore che non può essere negativo (forse per rappresentare un ID di un record del database). Inoltre, nessuno sembra mai utilizzare short/Int16 indipendentemente dalla capacità richiesta del valore.

Oggettivamente, ci sono casi in cui è meglio usare uint o short/Int16 e se sì, quali sono?

    
posta Alternatex 03.12.2014 - 17:26
fonte

5 risposte

24

Sospetto che ti stia riferendo a una prospettiva colorata dalle tue esperienze in cui non hai lavorato intorno a persone che usano correttamente i tipi interi. Questo potrebbe essere un evento comune, ma è stata la mia esperienza che le persone usano comunemente anche loro correttamente.

Il vantaggio è spazio di memoria e tempo di CPU, possibilmente anche spazio IO a seconda che i tipi siano mai stati inviati via cavo o su disco. I tipi non firmati forniscono controlli del compilatore per garantire che non vengano eseguite determinate operazioni impossibili, oltre a estendere l'intervallo disponibile mantenendo le dimensioni più ridotte per prestazioni elevate laddove potrebbe essere necessario.

L'uso corretto è come ti aspetteresti: ogni volta che conosci per certi puoi utilizzarli in modo permanente (non vincolare senza certezze o lo te ne pentirà più tardi)

  • Se stai cercando di rappresentare qualcosa che non potrebbe mai essere ragionevolmente negativo ( public uint NumberOfPeople ) usa un tipo senza firma.
  • Se stai cercando di rappresentare qualcosa che non potrebbe mai essere ragionevolmente maggiore di 255 ( public byte DamagedToothCount ), usa un byte.
  • Se stai cercando di rappresentare qualcosa che potrebbe essere ragionevolmente maggiore di 255, ma mai un numero significativo di migliaia , usa un breve ( public short JimmyHoffasBankBalance ).
  • Se stai cercando di rappresentare qualcosa che potrebbe essere centinaia di migliaia, anche milioni, ma difficilmente raggiungerai più miliardi, usa un int ( public int HoursSinceUnixEpoch ).
  • Se sai per certo che questo numero può avere un valore illimitato o se pensi che possa avere più miliardi, ma non sei sicuro di quanti miliardi, la tua scommessa migliore è lunga. Se lungo non è abbastanza grande hai un problema interessante e devi iniziare a guardare i numeri arbitrari di precisione ( public long MyReallyGreatAppsUserCountThisIsNotWishfulThinkingAtAll ).

Questo ragionamento può essere utilizzato ovunque nella scelta tra tipi di tipi firmati, non firmati e di vario tipo e altri, basti pensare alle verità logiche dei dati che stai rappresentando nella realtà.

    
risposta data 03.12.2014 - 17:50
fonte
15

Certo, ci sono casi in cui è meglio usare uint o short o Int16 . Quando conosci che il tuo intervallo di dati si adatta ai vincoli di quel tipo di variabile, allora va bene usare quel tipo.

In ambienti con vincoli di memoria o quando si ha a che fare con grandi quantità di oggetti, può avere senso usare la variabile di dimensione più piccola. Ad esempio, esiste una differenza significativa nelle dimensioni per un array di milioni di elementi di int s rispetto a short s.

Spesso, ciò non accade nel codice reale per uno o più dei seguenti motivi:

  • I vincoli di dati non erano noti in anticipo
  • C'era la possibilità che i vincoli dei dati non fossero solidi o che probabilmente si sarebbero modificati
  • Si sperava di riutilizzare la funzione con un intervallo di dati più ampio
  • Lo sviluppatore non ha avuto il tempo di pensare ai vincoli
  • I risparmi di memoria sono stati insignificanti per giustificare l'utilizzo di un tipo di variabile più piccolo

Ci sono molte più ragioni possibili, ma si riducono a questo: Il tempo necessario per decidere e utilizzare un tipo di variabile diverso non ha fornito un vantaggio sufficiente per giustificare l'operazione.

    
risposta data 03.12.2014 - 17:43
fonte
8

In C, in contesti che non coinvolgono la promozione di interi , i valori senza segno sono stati specificati per comportarsi come membri di un anello algebrico astratto "avvolgente" (quindi per qualsiasi X e Y, XY produrrà un valore univoco che, aggiunto a Y, produrrà X), mentre i tipi di interi con segno sono stati specificati come si comportano come numeri interi quando i calcoli sono rimasti all'interno di un certo intervallo e hanno permesso di fare qualsiasi cosa quando i calcoli andavano oltre. La semantica numerica in C #, tuttavia, è completamente diversa. Quando all'interno di un contesto numerico controllato, entrambi i tipi con segno e senza segno si comportano come numeri interi purché i calcoli rimangano nell'intervallo e generano OverflowException quando non lo fanno; in un contesto non controllato, si comportano entrambi come anelli algebrici.

L'unica volta in cui è generalmente utile utilizzare un tipo di dati più piccolo di Int32 è quando è necessario eseguire il packing o il disimballaggio di oggetti per lo storage o il trasporto compatto. Se è necessario memorizzare mezzo miliardo di numeri positivi e saranno tutti compresi nell'intervallo da 0 a 100, l'utilizzo di un byte ciascuno anziché di quattro consentirà di risparmiare 1,5 gigabyte di spazio di archiviazione. Questo è un grande risparmio. Se un pezzo di codice deve memorizzare un totale di un paio di centinaia di valori, tuttavia, rendendo ciascuno di essi un byte anziché quattro, si risparmiano circa 600 byte. Probabilmente non ne vale la pena.

Per quanto riguarda i tipi non firmati, le uniche volte che sono davvero utili sono quando si esegue lo scambio di informazioni o quando si suddividono i numeri in pezzi. Se, per esempio, uno ha bisogno di fare calcoli su interi a 96 bit, sarà probabilmente molto più semplice eseguire i calcoli su gruppi di tre interi a 32 bit senza segno, che su gruppi di interi con segno. Altrimenti, non ci sono molte situazioni in cui l'intervallo di un valore firmato a 32 o 64 bit sarebbe inadeguato, ma sarebbe sufficiente la stessa dimensione di valore senza segno.

    
risposta data 03.12.2014 - 23:33
fonte
4

In genere è una cattiva idea utilizzare tipi non firmati perché si sovrappongono in modi spiacevoli. x = 5-6 è improvvisamente una timebomb nel tuo codice. Nel frattempo i vantaggi dei tipi non firmati si riducono a un singolo extra di precisione, e se quel bit vale la pena per te, dovresti quasi sicuramente usare un tipo più grande.

Ci sono casi d'uso in cui un tipo più piccolo potrebbe avere senso, ma a meno che tu non sia preoccupato dell'uso della memoria o della necessità di comprimere i dati per l'efficienza della trasmissione o della cache o una manciata di altre preoccupazioni, di solito non c'è alcun vantaggio nell'usare un tipo più piccolo. Inoltre, su molte architetture, è più lento in realtà utilizzare questi tipi in modo che possano effettivamente imporre un piccolo costo.

    
risposta data 03.12.2014 - 20:27
fonte
2

Spesso dimenticata e possibilmente tangente alla tua domanda, quando si tratta specificatamente di tipi .NET, è CLS Compliance . Non tutti i tipi sono disponibili per tutte le lingue create in .NET Framework.

Se si sta scrivendo il codice per essere utilizzato da lingue diverse da C # e si desidera che tale codice garantisca l'interoperabilità con il maggior numero possibile di lingue .NET, è necessario limitare l'utilizzo del tipo a quelli compatibili con CLS.

Ad esempio, le prime versioni di VB.NET (7.0 e 7.1) non supportavano interi non firmati ( UInteger ):

http://msdn.microsoft.com/en-us/library/aa903459(v=vs.71).aspx

Gli interi non firmati non sono compatibili con CLS e quindi dovrebbero essere usati con cautela se non si è sicuri di chi sarà il consumatore della propria libreria di classi.

    
risposta data 09.12.2014 - 13:41
fonte

Leggi altre domande sui tag