5

誰かが説明を手伝ってくれるかどうか疑問に思っていた興味深い問題に遭遇しました。インターネット全体を検索してみましたが、この問題に対する答えが見つからないようです。私たちには解決策がありますが、他の人が同じ問題に遭遇する可能性があり、ランダムであるため、追跡するのは非常に困難です.

コンピューターが顧客の企業ネットワークに接続されている場合 (ネットワーク上に多くの情報がない場合)、ランダムに失敗するアプリケーションがあります。コンピューターを私たちの環境に持ち込んだとき、問題なく動作しました。エラーはかなりランダムですが、C# から管理されていないサード パーティ ベンダーの DLL への呼び出し中に発生したことがわかりました。私が持っているトレース バックの 1 つ (システム イベント ログにトレースを提供する 2 つのエラーのみ) は、アンマネージ DLL への呼び出しでのパラメーターのマーシャリング中の RtlMoveMemory 関数の ntdll.dll でのエラーを示しています。

アンマネージ関数の呼び出しは次のとおりです。

ThirdParty.CxxxAutomationWrapper clientDLL = new ThirdParty.CxxxAutomationWrapper () ;

object Parameter1 ;
  :
string theValue = "abcde" ;
Parameter1 = theValue ;
  :
if ( Parameter1 is string )
{
    int returnCode = clientDLL.function ( Parameter1 as string ) ;
}

呼び出しは、顧客のコンピューターで定期的に失敗しますが、Visual Studio (2010) 内で実行すると常に機能します。Parameter1 の値が正しく設定されています (決して null ではありません)。

呼び出しを次のように変更したため:

String parameter1String = Parameter1.ToString() ;
int returnCode = clientDLL.function ( parameter1String ) ;

すべてがうまくいきました。Parameter1 の値は厳密に制御されており、このコードが実行される前は null ではありません。

呼び出されるインターフェイス (clientDLL.function) は次のように定義されます。

HRESULT function ( [in] BSTR parameter,
                   [out, retval] long *ret);

C# の 'as' ステートメントについての [限られた?] 理解では、この最初のバージョンが失敗した理由がわかりません。「文字列として」指定されたパラメーターで呼び出されたときにこれが失敗する理由を説明できる人はいますか?

4

3 に答える 3

5

obj as stringobj.ToString()は同じではないからです。1 つ目は試行されたキャスト ( のようなものですが、失敗(string)objすると戻りnullます) であり、2 つ目はオブジェクトの文字列表現を返すメソッド呼び出しです。

実際には、型として文字列と互換性があるかどうかに関係なく、任意のオブジェクトの文字列表現を取得できますが、互換性がない場合、キャストは失敗します。

簡単な例:

object obj = new object(); // simple object
Console.WriteLine(obj.ToString()); // prints System.Object
Console.WriteLine((obj as string) == null); // True: obj is not a string!
于 2012-05-10T15:38:28.203 に答える
2

Parameter1.ToString()任意の .NET オブジェクトを文字列 (つまり のインスタンスSystem.String) にレンダリングします。が nullの場合、または のインスタンスでない場合は、Parameter1 as stringが返されます。実際の文字列ではなく、文字列をラップするクラスである場合、.nullParameter1System.Stringnull

もちろん、どちらもすべての場合に機能するわけではありません。のインスタンスがある場合System.StringnullParameter1 as stringを正しく返しますがnullParameter1.ToString()をスローしNullReferenceExceptionます。

安全なアプローチは次のとおりConvert.ToString(Parameter1)です。

于 2012-05-10T15:39:16.487 に答える
0

Parameter1 as stringと考えられる

string foo
try
{
    foo = (string)Parameter1;
}
catch
{
    foo = null;
}

どこ.ToString()ですか

string foo = Parameter1.ToString();

Parameter1 が文字列に直接キャストできないという事実が、失敗の原因です。

于 2012-05-10T15:44:56.173 に答える