2015-06-01 12 views

risposta

19

I tipi non firmati non sono conformi a CLS, quindi Stream.Write non utilizza uint per offset e conteggio.

Vedi: uint (C# Reference)

Il tipo uint non è compatibile con CLS. Utilizzare int quando possibile.

C'è un vecchio articolo: Why we don't have unsigned types in the CLS by Brad Abrams (2 Sep 2003) che spiega il motivo:

Tuttavia c'è un problema che continua ad emergere: Perché non abbiamo permettiamo tipi senza segno (UInt32 e simili) nel CLS?

Bene, ci sono davvero due risposte a questa domanda. Al primo livello alcune lingue (come VB.NET) non offrono il supporto completo per i tipi senza firma . Ad esempio, non è possibile avere valori letterali senza segno in VB.NET .... Ma per essere onesti non è una risposta completamente soddisfacente perché quando abbiamo avviato il CLS non è stato possibile creare sottoclasse in VB.NET , ma abbiamo esteso tale linguaggio per supportare ciò che sapevamo che le persone avrebbero voluto. . Avremmo potuto fare la stessa cosa con i tipi senza segno. Ma non l'abbiamo fatto. Perchè no? Bene, questo ha una ragione più profonda. Infatti lo stesso motivo per cui i primi beta del linguaggio C# non supportavano i tipi senza firma (nessun ushort, uint e simili).

La sensazione generale tra molti di noi è che la stragrande maggioranza dei programmazione avviene con i tipi firmati. Ogni volta che si passa ai tipi non firmati si forza uno switch modello mentale (e un cast brutto). Nel cast peggiore si crea un intero mondo parallelo di API che accettano tipi non firmati. Il valore di evitare il controllo "< 0" non vale l'inclusione di generici in il CLS.

(Si noti che la versione più recente di VB.Net (VB 8 in poi) supporta i tipi unsigned).

più cosa (probabilmente non correlato) di aggiungere uno, Stream.Write implementation ha i controlli per i valori negativi:

[System.Security.SecuritySafeCritical] // auto-generated 
public override void Write(byte[] array, int offset, int count) { 
    if (array==null) 
     throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer")); 
    if (offset < 0) 
     throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); 
    if (count < 0) 
     throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); 
    if (array.Length - offset < count) 
     throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); 
5

Dal uint MSDN only

Il tipo uint non è compatibile con CLS. Utilizzare int quando possibile.

Quindi Stream.Write utilizza int per offset e conteggio.

Il reasons given by ShuggyCoUk rende più chiaro:

  • uint non è compatibile con CLS, rendendo così incorporato in caratteri (array) dipendente da esso sarebbe stato problematico
  • Il runtime come originariamente progettato proibisce qualsiasi oggetto sullo heap che occupa più di 2 GB di memoria. Dal momento che la matrice di dimensioni massime che sarebbe inferiore a o uguale a questo limite sarebbe il nuovo byte [int.MaxValue] sarebbe sconcertante per le persone in grado di generare lunghezze di array positive ma illegali.
  • Storicamente C# eredita gran parte della sua sintassi e convenzione da C e C++. In questi array è semplicemente puntatore aritmetico, quindi era possibile indicizzare l'array in negativo (sebbene normalmente illegale e pericoloso). Poiché molto codice esistente presuppone che l'indice dell'array sia negativo, questo sarebbe stato un fattore
  • Su una nota correlata l'uso di numeri interi con segno per gli indici di matrice in C/C++ significa che l'interoperabilità con queste lingue e le funzioni non gestite richiederebbe l'uso di int in tali circostanze comunque, che può causare a causa dell'incongruenza.
  • Il BinarySearch attuazione (un componente molto utile di molti algoritmi) si basa sul fatto di poter utilizzare il campo negativo del int per indicare che il valore non stato trovato e la posizione in cui tale valore dovrebbe essere inserito in mantiene l'ordinamento.
  • Quando si opera su un array, è probabile che si contenda l'offset negativo di un indice esistente. Se hai utilizzato un offset che ti avrebbe portato oltre l'inizio dell'array usando l'unità allora il comportamento di avvolgimento renderebbe il tuo indice potenzialmente legale (nel senso che è positivo). Con un int il risultato sarebbe illegale (ma sicuro in quanto il runtime avrebbe guardia contro la lettura di memoria non valido)