8

次のコードは C# で正常に動作します。

    Int32 a, b;
    Int16 c;

    a = 0x7FFFFFFF;
    b = a & 0xFFFF;
    c = (Int16)b;

しかし、このコードはVB.NETで OverflowException でクラッシュします。

    Dim a, b As Int32
    Dim c As Int16

    a = &H7FFFFFFF
    b = a And &HFFFF
    c = CType(b, Int16)

どちらのコード スニペットも同じように見えます。違いは何ですか? また、C# コードを VB.NET に変換するにはどうすればよいですか?

4

7 に答える 7

11

MSDNから

算術演算、キャスト演算、または変換演算でOverflowExceptionをスローするには、チェックされたコンテキストで演算を実行する必要があります。デフォルトでは、VisualBasicの算術演算とオーバーフローがチェックされます。C#ではそうではありません。チェックされていないコンテキストで操作が発生した場合、宛先タイプに適合しない上位ビットを破棄することにより、結果が切り捨てられます。

編集:コードをC#からVB.NETに移植する場合は、それらの違いに興味があるかもしれません。また、コンパイラ設定を比較して、C#のデフォルト設定と同じになるように明示的に設定します(必要な場合)。

于 2009-12-09T14:19:14.483 に答える
8

最初に: これについての私の理解は、CType(b, Int16) は (Int16)b と同じではないということです。1 つは型の変換 (CType) で、もう 1 つはキャストです。(Int16)b は、CType(b, Int16) ではなく、DirectCast(b, Int16) と同等です。

(MSDN に記載されているように) 2 つの違いは、有効な変換がある限り CType が成功することですが、DirectCast ではオブジェクトの実行時の型が同じであることが必要です。設計時に、このオブジェクトがその型に変換するように指示するのではなく、その型であることをコンパイラに伝えています。

参照: http://msdn.microsoft.com/en-us/library/7k6y2h6x(VS.71).aspx

ただし、根本的な問題は、32ビット整数を16ビット整数に変換しようとしているということです...[必要な単語がありません。おそらく誰かがここに挿入してください]損失があります。16 ビットから 32 ビットへの変換はロスレスであるため許可されますが、32 ビットから 16 ビットへの変換は未定義です。C# で機能する理由については、@Roman の回答を参照してください。これは、C# がオーバーフローをチェックしないという事実に関連しています。

UInt16.MaxValueの結果の値&H7FFFFFFF And &HFFFF(65535) UInt16 は 0 から 65535 まで実行されます。-32768 から 32767 まで実行される Int16 にそれを詰め込もうとしていますが、ご覧のとおり動作しません。また、この値が UInt16 に収まる可能性があるという事実は偶然であり、2 つの 32 ビット整数を追加して 16 ビット整数 (ショート) に詰め込もうとすると、オーバーフローが頻繁に発生するため、これは本質的に危険な操作であると言えます。

于 2009-12-09T14:09:21.710 に答える
2

使ってみましたDirectCast(b, Int16)か?CType は C# キャストと同じではありません。

と のパフォーマンスを比較した記事と、DirectCastどちらCTypeを使用する必要があるかについて詳しく説明した記事を次に示します。

于 2009-12-09T14:08:33.693 に答える
1

http://www.cnblogs.com/liujq007/archive/2010/12/04/1896059.html

概要:

符号なしタイプの場合: And 演算子または 2 番目のメソッドを実行するだけです。

Dim a As Byte = CByte(300 And &HFF)

符号付き型へ: 左シフト n ビット、次に右シフト n ビット。符号付きビットを展開します。n = (sizeof(type1) - sizeof(type2)) * 8 または VB: sizeof(type) の代わりに Len(New type) を使用

Dim a As Short = CShort(34042 << 16 >> 16)

詳細は下記リンクよりご覧いただけます。

于 2010-12-06T07:59:43.437 に答える
0
?CType(b, Int16)
Constant expression not representable in type 'Short'.

?b
65535

?directcast(b, Int16)
Value of type 'Integer' cannot be converted to 'Short'.

?int16.TryParse(b.ToString(), c)
False
于 2009-12-09T14:17:56.467 に答える
0

この種のオーバーフローは、構造体で切り捨てることができます。

<StructLayout(LayoutKind.Explicit)> _
Public Structure int3216
    <FieldOffset(0)> Public i32 As Int32
    <FieldOffset(0)> Public i16high As Int16
    <FieldOffset(2)> Public i16low As Int16
End Structure

...

  Dim _i3216 As int3216
  _i3216.i32 = a And &HFFFF
  c = _i3216.i16low
于 2010-03-03T04:17:12.997 に答える
0

Short を変換し、オーバーフロー エラーなしでオーバーフロー結果を取得するための解決策を探しているときに、この質問に遭遇しました。ここで解決策を見つけました:

http://bytes.com/topic/visual-basic-net/answers/732622-problems-typecasting-vb-net

ページの約半分は次のとおりです。

古い VB の "適切な" トリックである "サイドステップ" から 16 進数へのアウトとバックは、まだ機能します。

Dim unsigned as UInt16 = 40000
Dim signed as Int16 = CShort(Val("&H" & Hex(unsigned)))

それはかなり滑らかに動作するようです!

于 2015-09-23T15:36:34.547 に答える