Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy bits from ulong to long in C#

So it appears that the .NET performance counter type has an annoying problem: it exposes long for the counter RawValue while the actual perf counter value in windows is unsigned and cannot be negative. For instance if you have a NumberOfItems64 counter The API will be perfectly happy to accept a negative value, then silently convert it to a very large number. In fact for half the value range of the counter the only way to set it there is to find the correct negative value to pass in!

I assume what is happening here is that they are taking the raw bits from the long and treating it as an unsigned 64-bit number. The negative values from two's complement are just read as a straight up number for the counter.

So I'm trying to figure out how to coerce C# into just dropping the bits from the ulong straight into the long, since that's what the API wants. But C# is being too helpful here... you can't cast or use Convert.ToInt64(ulong) since it throws overflow exceptions because of the value being too large. I stumbled upon this way of doing the conversion:

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

When it converts from a string in non-base 10 it assumes the number is in two's complement and does what I need it to. But it's not ideal because it needs to allocate an object and parse a string for every conversion and this API is going to be performance-critical. Is there a better way in C# to do this?

like image 878
RandomEngy Avatar asked Oct 24 '12 19:10

RandomEngy


1 Answers

A simple cast like

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

preserves the bits in the value exactly.

like image 178
dtb Avatar answered Sep 23 '22 16:09

dtb