2012-10-24 17 views
11

Quindi sembra che lo .NET performance counter type abbia un problema fastidioso: espone long per il contatore RawValue mentre il valore effettivo del contatore di perf in windows non è firmato e non può essere negativo. Ad esempio se hai un contatore NumberOfItems64 L'API sarà perfettamente felice di accettare un valore negativo, quindi convertirlo silenziosamente in un numero molto grande. Infatti per metà del range di valori del contatore l'unico modo per impostarlo è trovare il valore negativo corretto da inserire!Copia di bit da lungo a lungo in C#

Suppongo che ciò che sta accadendo qui è che stanno prendendo i bit grezzi dal long e lo trattano come un numero a 64 bit senza segno. I valori negativi del complemento a due vengono letti come numero di scala per il contatore.

Quindi sto cercando di capire come forzare C# nel lasciare semplicemente i bit dallo ulong direttamente allo long, poiché è ciò che l'API vuole. Ma C# è troppo utile qui ... non puoi trasmettere o utilizzare Convert.ToInt64(ulong) poiché genera eccezioni di overflow a causa del valore troppo grande. Mi sono imbattuto in questo modo di fare la conversione:

Convert.ToInt64(myULong.ToString("X"), 16)

Quando si converte da una stringa in non-base 10 assume il numero è in complemento a due e fa quello ho bisogno di. Ma non è l'ideale, perché ha bisogno di allocare un oggetto e analizzare una stringa per ogni conversione e questa API sarà critica dal punto di vista delle prestazioni. C'è un modo migliore in C# per fare questo?

+0

Puoi fornire un esempio di codice che causa il problema dell'eccezione di overflow in un cast? Posso fare 'long signed = long.MaxValue; firmato ++; ulong unsigned = (ulong) signed; 'senza eccezioni. –

+1

@Will: stai compilando con '/ checked +'? Il comportamento potrebbe cambiare. Inoltre, si potrebbe semplicemente dire "ulong unsigned = (ulong) long.MinValue;" e "long signed = (long) ulong.MaxValue;", che conservano entrambi i bit ma modificano il valore. –

+0

@ Ben - Buona domanda - Sto solo eseguendo Linqpad, quindi non sono sicuro di quali siano le impostazioni. –

risposta

18

Un semplice getto come

ulong value1 = 0xFEDCBAUL; // 18364758544493064720 
long value2 = (long)value1;   // -81985529216486896 
ulong value3 = (ulong)value2;   // 18364758544493064720 

conserva i bit del valore esattamente.

+1

No, voglio copiare i bit da un ulong a un long, non convertire un long a un ulong. – RandomEngy

+6

Questo farà una conversione binaria dei bit. Non so perché questo è downvoted. La copia dei bit è la stessa della conversione. Si potrebbe voler aggiungere 'deselezionato (...)'. – usr

+1

@usr Ho downvoted la modifica originale (prima di quella ninja che ha prodotto la versione corrente), perché il cast è andato nella direzione sbagliata. +1 per 'deselezionata'. –