4

根据问题“我可以将 long 转换为 int 吗? ”,在 C# 中将 long 转换为 int 的最佳方法是:

int myIntValue = unchecked((int)myLongValue);

如何在 VB.NET 中做到这一点?据我了解,VB.NET 没有未检查的概念。

当我在转换器中转换代码时,它说使用 CInt()。但是 CInt 抛出了一个 system.overflowexception。在 C# 中使用 unchecked 可以防止 system.overflowexception。

我宁愿不捕捉异常。

Dim x As Long = Int32.MaxValue
x = x + 100
Console.WriteLine(x)

Dim y As Integer = CInt(x)
Console.WriteLine(y)
4

6 回答 6

7

正如您在我的相关类似问题的答案中看到的那样,有很多方法可以做这种事情,但没有什么比一个简单的Try/Catch块更方便的了。如果你想避免一个Try/Catch块的低效率,我建议先检查该值,如下所示:

If (myLongValue >= Integer.MinValue) AndAlso (myLongValue <= Integer.MaxValue) Then
    myIntValue = CInt(myLongValue)
End If

或者,如果您想将值设置为超出范围时的特定值:

If myLongValue < Integer.MinValue Then
    myIntValue = Integer.MinValue
ElseIf myLongValue > Integer.MaxValue Then
    myIntValue = Integer.MaxValue
Else
    myIntValue = CInt(myLongValue)
End If

如果你想让它更方便,你可以让它成为一个函数。如果方便是最终目标,您甚至可以将其作为扩展方法:

<Extension>
Public Function AsInt32(value As Long) As Integer
    If value < Integer.MinValue Then
        Return Integer.MinValue
    ElseIf value > Integer.MaxValue Then
        Return Integer.MaxValue
    Else
        Return CInt(value)
    End If
End Function
于 2014-11-05T19:07:52.843 回答
1

是否已经编写了一个转换函数来检查它是否大于它,如果不是,将它设置为Int32.MaxValue

不,但这很简单:

Dim l as Long = Int32.MaxValue + 12433243243

Dim i as Int32
if l > int32.MaxValue Then
   i = int32.MaxValue
elseIf l < int32.MinValue
   i = int32.MinValue
Else
   i = CInt(l)
End If

或者在一行中:

i = if(l > int32.MaxValue, int32.MaxValue, if(l < int32.MinValue, int32.MinValue, CInt(l)))

或使用Math.Min

i = CInt(Math.Max(Math.Min(l, int32.MaxValue), int32.MinValue))
于 2014-11-05T19:07:44.813 回答
1

这是将 long 转换为 int 的一种相当轻松的方法,只需提取低 32 位而不抛出异常。没有 64 位除法,没有 try/catch 块,只是位旋转和单个比较​​。

Private Function CastLongToInt(x As Long) As Integer
    Dim value As Integer = CType(x And &H7FFFFFFFL, Integer) ' get the low order 31 bits

    ' If bit 32 (the sign bit for a 32-bit signed integer is set, we OR it in
    If (0 <> (x And &H80000000L)) Then
        value = value Or &H80000000I
    End If

    Return value
End Function

这是一个更简单的演绎——只是有点玩弄。根本没有比较。我们只需抓取 2 个 16 位半字节并将它们组合成最终值:

Private Function CastLongToInt(x As Long) As Integer
    Dim hiNibble As Integer = &HFFFFL And (x >> 16) 
    Dim loNibble As Integer = &HFFFFL And x
    Dim value As Integer = (hiNibble << 16) Or loNibble
    Return value
End Function

编辑注意:

另一种选择是使用可为空的整数 ( System.Nullable<int>)。在 VB.Net 中,它会是这样的:

Private Function TryCastLongToInt(x As Long) As Integer?
    Dim value As Integer?
    Try
        value = CType(x, Integer)
    Catch
      ' This exception intentionall swallowed here
    End Try
    Return value
End Function

或者,如果故意捕获和吞下异常的概念困扰您:

Private Function TryCastLongToInt(x As Long) As Integer?
    If (x < Integer.MinValue) Then Return Nothing
    If (x > Integer.MaxValue) Then Return Nothing
    Return x
End Function

Nothing无论哪种方式,如果 64 位值在 32 位整数的域之外,则返回值将是一个整数值。

于 2014-11-05T20:17:44.373 回答
0

您可以将 mod 函数与 Convert.ToInt32 一起使用:

i = Convert.ToInt32(x Mod (Int32.MaxValue))
于 2014-11-05T19:10:34.837 回答
0

执行这种操作的无分支方式是:

Function UInt64ToInt32Wrap(v As UInt64) As Int32
    Return CInt((CUInt(v And &HFFFFFFFFUI) Xor &H80000000UI) + &H80000000)
End Function
Function Int64ToInt32Wrap(v As Int64) As Int32
    Return CInt(((v And &HFFFFFFFFL) Xor &H80000000L) + &H80000000)
End Function
Function UInt32ToInt32Wrap(v As UInt32) As Int32
    Return CInt((v Xor &H80000000UI) + &H80000000)
End Function

请注意,在每种情况下,最后一个十六进制值都是Int32值为 -2147483648,因此将其添加到无符号类型将导致提升为Int64; 将其添加到先前 XOR 的结果将始终产生一个在Int32.

我希望其中一个类似的东西作为编译器内在提供,因为即使操作是无分支的并且 JIT 可能会将所有内容简化为 32 位“xor”和 32 位“add”指令,它不应该不必使用任何代码来完成此操作。

顺便说一句,我认为另一种方法是定义一个结构,该结构具有覆盖 anInt32和 a的“LayoutKind.Explicit”属性UInt32;这可能会消除不必要的相互取消算术运算,但它可能会强制抖动将值存储到内存并在它可以将事物保存在寄存器中时重新加载它。

于 2014-11-05T19:30:39.703 回答
0

到目前为止很好的答案,这是另一个类似于 Steven Doggart 的答案:

Dim x As Long = Int32.MaxValue
x = x + 100
Console.WriteLine(x)

Dim y As Integer
If x > Int32.MaxValue Then y = Int32.MaxValue Else y = x
Console.WriteLine(y)

结果:

2147483747
2147483647

或者:

Dim x As Long = Long.MaxValue
Console.WriteLine(x)

Dim y As Integer
If x > Int32.MaxValue Then y = Int32.MaxValue Else y = x
Console.WriteLine(y)

结果:

9223372036854775807
2147483647

将其包装在一个函数中:

Function DownsizeLongToInt(ByVal x As Long) As Integer
    Dim y As Integer
    If x > Int32.MaxValue Then y = Int32.MaxValue Else y = x
    Return y
End Function

注意函数名称。我以这种方式命名它以表明这将导致截断/数据丢失,并且不应用于将 Long 转换为 Int,这可能是有损的,这也可能是各种转换的原因函数不会尝试这样做。只是一个猜测。

于 2014-11-05T21:05:48.853 回答