I needed this functionality for map compression (height and validity to take up 2 bytes rather than 3 bytes), which would have been much easier if the height wasn't signed. I did some research about sign extension, so here's a cool little method allowing for sign extension on a data type of any bit size less than 8 bytes, rather than a byte power of 2. This method also allows for truncation to any primitive numerical data type giving the same result. It treats the most significant bit as the sign. It's also optimized and has an xml comment because yolo swag.
If generics allowed for a constraint on only numerical types allowing for the sizeof operation and exposing MaxValue and MinValue, this could be perfect :(.
Note: You could hardcode 64 in place of sizeof(long) << 3, but I'm not sure if data type sizes vary. Also, I'd make an overload to use ints instead of long as it's more optimized for 32-bit systems.
Code:
/// <summary>
/// Sign extends a value of the specified size (in bits).
/// </summary>
/// <param name="value">The value to sign extend.</param>
/// <param name="bitSize">The size of the value in bits.</param>
/// <returns>A sign extended value.</returns>
long SignExtend(long value, int bitSize)
{
int counterBitSize = (sizeof(long) << 3) - bitSize;
return (value & (long.MaxValue >> (counterBitSize - 1))) << counterBitSize >> counterBitSize;
}
Note: You could hardcode 64 in place of sizeof(long) << 3, but I'm not sure if data type sizes vary. Also, I'd make an overload to use ints instead of long as it's more optimized for 32-bit systems.