Dot-Net

如何在沒有OverflowException的情況下將無符號整數轉換為有符號整數

  • April 8, 2019

我希望能夠將高值無符號整數(使用最高位的值)轉換為有符號整數。在這種情況下,我不在乎該值是否高於有符號整數類型的最大值。我只是希望它轉換為任何位值表示為有符號整數。換句話說,我希望它會產生一個負數。

但是,對於 VB.NET,該CType操作不能以這種方式工作(或任何其他轉換函式,如CShortand CInteger)。當您嘗試轉換高於所需有符號類型最大值的無符號值時,它會拋出一個OverflowException而不是返回一個負數。例如:

Dim x As UShort = UShort.MaxValue
Dim y As Short = CShort(x)  ' Throws OverflowException

同樣值得一提的是,該DirectCast操作不能用於在有符號和無符號類型之間轉換值,因為這兩種類型都不繼承或實現另一個。例如:

Dim x As UShort = UShort.MaxValue
Dim y As Short = DirectCast(x, Short)  ' Won't compile: "Value of type 'UShort' cannot be converted to 'Short'

我已經想出了一種方法來做我想做的事,但這似乎不必要地難看。這是我如何讓它工作的:

Dim x As UShort = UShort.MaxValue
Dim y As Short = BitConverter.ToInt16(BitConverter.GetBytes(x), 0)  ' y gets set to -1

就像我說的那樣,這行得通,但是如果在 VB.NET 中有更簡單、更清潔的方法,我很想知道它是什麼。

如果您經常使用它,那麼持續使用BitConverter會有點不方便——尤其是在性能方面。如果那是我,我會非常想在 C# 中添加一個可以進行直接轉換的實用程序庫(通過unchecked,儘管unchecked通常是 C# 中的預設值*)*,並為此引用該庫。另一種選擇可能是濫用“聯合”結構;以下應該很容易轉換為VB:

[StructLayout(LayoutKind.Explicit)]
struct EvilUnion
{
   [FieldOffset(0)] public int Int32;
   [FieldOffset(0)] public uint UInt32;
}
...
var evil = new EvilUnion();
evil.Int32 = -123;
var converted = evil.UInt32;

IE

<System.Runtime.InteropServices.StructLayout(Runtime.InteropServices.LayoutKind.Explicit)>
Structure EvilUnion
   <System.Runtime.InteropServices.FieldOffset(0)>
   Public Int32 As Integer
   <System.Runtime.InteropServices.FieldOffset(0)>
   Public UInt32 As UInteger
End Structure
...
Dim evil As New EvilUnion
evil.Int32 = -123
Dim converted = evil.UInt32

我認為最簡單的方法如下:

Public Function PutSign(ByVal number As UShort) As Short
   If number > 32768 Then 'negative number
       Return (65536 - number) * -1
   Else
       Return number
   End If
End Function

引用自:https://stackoverflow.com/questions/14708778