如何在没有OverflowException的情况下将无符号整数转换为有符号整数

Ste*_*art 11 .net vb.net casting overflowexception bitconverter

我希望能够将高值无符号整数(使用最高位的值)转换为有符号整数.在这种情况下,我不关心该值是否高于有符号整数类型的最大值.我只是希望它转换为位值表示的有符号整数.换句话说,我希望它会导致负数.

但是,使用VB.NET,CType操作不会以这种方式工作(或任何其他转换函数,如CShortCInteger).当您尝试转换高于所需签名类型的最大值的无符号值时,它会抛出OverflowException而不是返回负数.例如:

Dim x As UShort = UShort.MaxValue
Dim y As Short = CShort(x)  ' Throws OverflowException
Run Code Online (Sandbox Code Playgroud)

值得一提的是,该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'
Run Code Online (Sandbox Code Playgroud)

我找到了一种方法来做我想做的事,但它看起来不必要的丑陋.以下是我如何使用它:

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

就像我说的那样,但是如果在VB.NET中有一种更简单,更清晰的方式,我很想知道它是什么.

Mar*_*ell 14

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;
Run Code Online (Sandbox Code Playgroud)

<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
Run Code Online (Sandbox Code Playgroud)