Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Marshalling "as string" parameter from C#

Ran into an interesting problem that I was wondering if anyone can help explain. I have tried searching all over the internet and can’t seem to find an answer to this problem. While we have a solution, others might run into the same problem, and since it was random, it is very hard to track down.

We have an application that randomly fails when the computer is attached to the customers corporate network (don’t have a lot of information on the network). When we brought the computer to our environment it worked fine. The failure is fairly random, but as best as I could figure out occurred during calls from C# to an unmanaged third party vendors DLL. One of the trace backs I do have (only a couple failures provided traces in the system event log) points to a failure in ntdll.dll in the RtlMoveMemory function during the marshalling of parameters in calls to the unmanaged DLL.

The call to the unmanaged function was:

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

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

The call periodically fails on the customers computer but always works when run within Visual Studio (2010). The value of Parameter1 is correctly set (never null).

Since I changed the call to:

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

everything has worked fine. The value of Parameter1 is very controlled and is not null prior to this code being executed.

The interface being called (clientDLL.function) is defined as:

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

With my [limited?] understanding of the ‘as’ statement in c#, I don’t understand why the first version of this failed. Can anybody help explain why this fails when called with the parameter specified as “as string”?

like image 356
Richard Bousman Avatar asked May 10 '12 15:05

Richard Bousman


2 Answers

Because obj as string and obj.ToString() are not the same. The first is an attempted cast (sort of like (string)obj, but which returns null upon failure), while the seconds is a method call returning a string representation of the object.

Practically you can get the string representation of any object regardless of whether it's compatible with string as type, but the cast will fail if they are not compatible.

Simple example:

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!
like image 53
Tudor Avatar answered Nov 17 '22 13:11

Tudor


Parameter1.ToString() will render any .NET object to a string (i.e. instance of System.String). Parameter1 as string will return null if Parameter1 is null or if it is not an instance of System.String. If it is a class that wraps a string rather than actually being one, then you will end up with a null.

Neither will work in every case of course. If you have an instance of System.String which is null, then Parameter1 as string would correctly return null, whereas Parameter1.ToString() would throw a NullReferenceException.

A safe approach would be: Convert.ToString(Parameter1).

like image 2
David M Avatar answered Nov 17 '22 13:11

David M