none
配列変数からのキャストについて RRS feed

  • 質問

  • 開発環境

    Win7 Pro、.NET FramWork4

    現在VB6⇒VB.NETへ書き直しております

    'COMポートから受信
    Private Function RsRxd(pRxdBuff() As Byte, RxdSize As Long) As Long
    '受信タイムアウト時は、-10が戻る
       
        Dim ComOcx As Object            'mscommへの参照を入れる
        Dim rxbuff As Variant        ←←.NETの場合、Object型で宣言
        Dim l As Long
        Dim lTime As Long
       
        lTime = timeGetTime()
        ComOcx.InputLen = RxdSize
        Do
            If ComOcx.InBufferCount >= RxdSize Then     'RxdSize受信するまでloop
                Exit Do
            End If
            'タイムアウトcheck:とりあえず15秒
            If (timeGetTime() - lTime) > 15000 Then
                RsRxd = -10     'タイムアウト
                Exit Function
            End If
        Loop
        rxbuff = ComOcx.Input     ←ここで『'System.String'のオブジェクトを型'System.Arrayにキャストできません'』
        For l = 0 To UBound(rxbuff)
            pRxdBuff(l) = rxbuff(l)
        Next

    そこで、上記のVB6のプログラムにおいて、VB6ではエラーになりませんが、VB.NETの場合、変数に値を入れようとするとエラーが発生します。

    VB6とVB.NETでのソースの違いは、変数宣言においてVB.NETではVariant型がない為、Object型で宣言しています。

    イミディエイトウィンドウで『ComOcx.Input』を見ても、配列の場合、『??』と表示され、rxbuff(l)を中を見た場合、『48』、『70』等の数値が入っています。

    配列でない変数に配列変数を入れようとしている為エラーになるのは分るのですが、どのようにキャストしたら良いか分らず、投稿させて頂きました。

    初歩的な質問かもしれませんが、何卒宜しくお願い申し上げます。

    2014年9月2日 9:59

回答

  • 質問するときは開発環境のバージョンをきちんと書きましょう。.NET Frameworkのバージョンだけでは不十分です。多分VB.NET 2010あたりだとは思いますが……
    まず、VB.NETには旧Visual Basicにおける邪悪なVariant型は存在しません。.NETのObject型はまったくの別物で、互換性がないことに注意してください。また、VB.NETではIntegerが32bitに、Longが64bitになります。
    肝心の、コンパイルエラーだかランタイムエラーだかが発生しているとかいうVB.NETのほうのコードがきちんと提示されてないので、これは予測になりますが、System.String型(にマーシャリングされた)InputプロパティをSystem.Arrayに無理やりキャストするとかいうようなことをしているのですか?
    もしString中の各文字(ASCII前提)をインデクサで取得したいだけなのであれば、

    pRxdBuff(i) = CType(Val(comOcx.Input(i)), Byte)

    のような形で書けると思います。
    なお、.NET 2.0以降では、System.IO.Ports.SerialPortクラスが追加されているので、今後はそちらを使ったほうがよいと思います。無理に古いコンポーネントを使う必要はありません。なお、複雑なことをしようとする前に、まず入門サイトか何かで旧VBとVB.NETの根本的な違いをきちんと勉強してからにしたほうがよいと思います。
    • 編集済み sygh 2014年9月2日 17:19
    • 回答としてマーク kong0214 2014年9月3日 0:21
    2014年9月2日 17:16
  • ComOcxというのはMS Comm Control 6.0(MSCOMM32.ocx)でしょうか?
    であればInputを読み取る前の適当なところに

    ComOcx.InputMode = MSCommLib.InputModeConstants.comInputModeBinary

    というコードを挿入してください。
    そうするとInputはバイト配列を返すようになります。

    逆にMSCommLib.InputModeConstants.comInputModeTextが設定されているとInputは文字列と変換されて返されます。
    UBoundの引数には配列を与えないといけないのに、文字列はArray(配列)にキャストできないので、その結果としてエラーとなります。

        rxbuff = ComOcx.Input 'InputModeConstants.comInputModeTextになっているとInputは文字列になる 
        For l = 0 To UBound(rxbuff)'←正しくはここで『'System.String'のオブジェクトを型'System.Arrayにキャストできません'』が発生します。
            pRxdBuff(l) = rxbuff(l)
        Next
    元のVB6でバイナリで受信してたならcomInputModeBinaryを指定しましょう。

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク kong0214 2014年9月3日 0:26
    2014年9月2日 18:09

すべての返信

  • ソースと質問文が合っていない気がするのですが、キャストというか、とりあえずコレクションでしょうか?

    (参考)
    ジェネリック・クラスで変わるC#とVBのコレクション (2/4)
    http://www.atmarkit.co.jp/ait/articles/0602/11/news011_2.html

    #Listより高速なLinkedListもあります。ただし、良い面ばかりではありません。Listで性能が出なければ、試されてみてもよいと思います。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2014年9月2日 16:50
    モデレータ
  • 質問するときは開発環境のバージョンをきちんと書きましょう。.NET Frameworkのバージョンだけでは不十分です。多分VB.NET 2010あたりだとは思いますが……
    まず、VB.NETには旧Visual Basicにおける邪悪なVariant型は存在しません。.NETのObject型はまったくの別物で、互換性がないことに注意してください。また、VB.NETではIntegerが32bitに、Longが64bitになります。
    肝心の、コンパイルエラーだかランタイムエラーだかが発生しているとかいうVB.NETのほうのコードがきちんと提示されてないので、これは予測になりますが、System.String型(にマーシャリングされた)InputプロパティをSystem.Arrayに無理やりキャストするとかいうようなことをしているのですか?
    もしString中の各文字(ASCII前提)をインデクサで取得したいだけなのであれば、

    pRxdBuff(i) = CType(Val(comOcx.Input(i)), Byte)

    のような形で書けると思います。
    なお、.NET 2.0以降では、System.IO.Ports.SerialPortクラスが追加されているので、今後はそちらを使ったほうがよいと思います。無理に古いコンポーネントを使う必要はありません。なお、複雑なことをしようとする前に、まず入門サイトか何かで旧VBとVB.NETの根本的な違いをきちんと勉強してからにしたほうがよいと思います。
    • 編集済み sygh 2014年9月2日 17:19
    • 回答としてマーク kong0214 2014年9月3日 0:21
    2014年9月2日 17:16
  • ComOcxというのはMS Comm Control 6.0(MSCOMM32.ocx)でしょうか?
    であればInputを読み取る前の適当なところに

    ComOcx.InputMode = MSCommLib.InputModeConstants.comInputModeBinary

    というコードを挿入してください。
    そうするとInputはバイト配列を返すようになります。

    逆にMSCommLib.InputModeConstants.comInputModeTextが設定されているとInputは文字列と変換されて返されます。
    UBoundの引数には配列を与えないといけないのに、文字列はArray(配列)にキャストできないので、その結果としてエラーとなります。

        rxbuff = ComOcx.Input 'InputModeConstants.comInputModeTextになっているとInputは文字列になる 
        For l = 0 To UBound(rxbuff)'←正しくはここで『'System.String'のオブジェクトを型'System.Arrayにキャストできません'』が発生します。
            pRxdBuff(l) = rxbuff(l)
        Next
    元のVB6でバイナリで受信してたならcomInputModeBinaryを指定しましょう。

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク kong0214 2014年9月3日 0:26
    2014年9月2日 18:09
  • まさに、その通りでした。

    テキストモードにしておりましたので、バイナリモードに変更したら上手くいきました。

    受け取り側の変数を何とか配列型に入れる方法を考えてばかりおりましたが、そもそもの元データと変数を理解してないばかりに悩んだ結果ですね。

    本当に助かりました。

    また、【System.IO.Ports.SerialPort】を使用した方が良いとのアドバイスですが、その通りだと思います。VB6のプログラムをVB.NETへの転記が完了し、プログラムの稼働が確認出来たら書き直す予定で御座います。

    以上、本当に有難うございました。

    • 編集済み kong0214 2014年9月3日 0:37
    2014年9月3日 0:26