3

こんにちは、C# .NET のコードに問題がありました。OPC サーバーに接続するために DLL を使用しています。この DLL は VB.NET プロジェクトで使用され、まったく問題なく動作します。

ListBox で使用可能なサーバーのリストを表示しようとしています。VB.NET で使用されている (そして動作する) コードは次のとおりです。

Dim AllOPCServers As Object
AllOPCServers = AnOPCServer.GetOPCServers

' Load the list returned into the List box for user selection
Dim i As Short
For i = LBound(AllOPCServers) To UBound(AllOPCServers)
    AvailableOPCServerList.Items.Add(AllOPCServers(i))
Next i

そして、私はこれをC#アプリケーションで使用するために書きました

try
{
    var _listOPCServer = _OPCServer.GetOPCServers();
    foreach(var i in _listOPCServer)
    {
        string serverName = (string)i;
        listServers.Items.Add(serverName);
    }             
}
catch (Exception exc)
{
    lstMsg.Items.Add(DateTime.Now + " Error al Obtener Lista de OPC's: " + exc.Message);
}

[ローカル] タブのデバッグ モードでは、次のように表示されます。

_listOPC サーバー | {文字列[1..2]} | ダイナミック {文字列[]} |

[1]        |  "Server01"    | string  
[2]        |  "Server02"    | string

アップデート:

「foreach(var i in _listOPCServer )」の行にエラーが表示されます

オブジェクト型 'System.String[*]' を型 'System.String[]' にキャストできません

それが実際のエラーです。

私は何か間違ったことをしていると確信しています、誰かが私を助けることができますか?

4

3 に答える 3

4

OK、私はこれを解決する方法を見つけました。それはあなたのアドバイスのモッドにすぎません

 Array _listOPCServer = (Array)(object)_OPCServer.GetOPCServers();               

            foreach(object i in _listOPCServer)
            {
                string serverName = (string)i;
                listServers.Items.Add(serverName);
            }             

宣言に (object) を追加しただけで正常に動作し、希望どおりにサーバーのリストを表示できるようになりました

またはこれを行う

Array _listOPCServer = (Array)(object)_OPCServer.GetOPCServers();               

            foreach(object i in _listOPCServer)
            {
                listServers.Items.Add(i);
            }

繰り返しますが、あなたの助けと時間をありがとう!

于 2012-09-14T19:26:44.803 に答える
2

VB.NETは、不適合な配列タイプを処理するのにはるかに鋭敏です。.NETを使用すると、言語を相互に簡単に相互運用できます。

問題は、OPCがCOMベースの標準であるということです。使用しているサーバーは、不適合な下限を持つSAFEARRAYを返しています。最初のインデックスは1です。0ではありません。COMではそれほど珍しいことではありません。最初の配列インデックスとして0と1のどちらかを選択することは、エンディアンの問題のようなものです。トマトは果物または野菜です(それは果物です。そしてリトルエンディアンは正しい種類の野菜です)。

ただし、下限としての0は、C#が1次元配列を処理するときに主張するものです。これには、下限が0の1つの次元を持つ別個の配列型である「ベクトル」が必要です。.NETランタイムで大幅に最適化されています。返されるものは一致しないため、 1次元の多次元配列にマップされます。C#言語で表現できる配列型ではありません。

C#でハックすることはできますが、配列型を明示的に使用する必要があります。このようなものは、明確にするために綴られています。

Array servers = (Array)_OPCServer.GetOPCServers();
int first = servers.GetLowerBound(0);
int last = servers.GetUpperBound(0);
for (int ix = first; ix <= last; ++ix) {
    var elem = (string)servers.GetValue(ix);
    // etc..
}
于 2012-09-14T00:02:57.723 に答える
1

Hans はゼロベースの配列と非ゼロベースの配列の違いを区別する点で正しいですが、その例外が発生する理由はまだわかりません。

私の推測では、実行時まで型バインディングを延期する_OPCServerasを宣言していると思います。dynamicこのよう_listOPCServerdynamicもです。

配列を反復処理してstrings を抽出しているため、コンパイラオブジェクトを にキャストしようとしている可能性がありますがstring[]、Hans が指摘しているように無効です。

_listOPCServerにキャストしてArray、そのまま使用できるはずforeachです。

Array _listOPCServer = (Array)(_OPCServer.GetOPCServers());
foreach(var i in _listOPCServer)
{
    // etc.
于 2012-09-14T01:11:10.453 に答える