2012-05-10 12 views
5

Se produjo un problema interesante que me preguntaba si alguien puede ayudarme a explicarlo. Intenté buscar en Internet y parece que no puedo encontrar una respuesta a este problema. Si bien tenemos una solución, otros pueden encontrarse con el mismo problema, y ​​dado que fue aleatorio, es muy difícil localizarlo.Alinear el parámetro "como cadena" de C#

Tenemos una aplicación que falla al azar cuando la computadora está conectada a la red corporativa del cliente (no tiene mucha información en la red). Cuando llevamos la computadora a nuestro entorno funcionó bien. La falla es bastante aleatoria, pero lo mejor que pude averiguar ocurrió durante las llamadas de C# a una DLL de proveedores externos no administrados. Uno de los rastreos que tengo (solo un par de fallas proporcionaron trazas en el registro de eventos del sistema) apunta a un error en ntdll.dll en la función RtlMoveMemory durante la clasificación de los parámetros en las llamadas a la DLL no administrada.

La llamada a la función no administrada fue:

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

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

la llamada falla periódicamente en el equipo de los clientes, pero siempre funciona cuando se ejecuta dentro de Visual Studio (2010). El valor de Parameter1 está configurado correctamente (nunca nulo).

Desde que cambié la llamada a:

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

todo ha funcionado bien. El valor de Parameter1 está muy controlado y no es nulo antes de que se ejecute este código.

La interfaz se llama (clientDLL.function) se define como: [? Limitado]

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

Con mi comprensión del 'como' declaración en C#, no entiendo por qué la primera versión de esto falló ¿Alguien puede ayudar a explicar por qué falla cuando se llama con el parámetro especificado como "como cadena"?

+0

Actualicé la publicación original en respuesta a las respuestas que recibí para ayudar a aclarar el problema. Las actualizaciones incluyen mostrar cómo se declara y se asigna el parámetro1, y poner un if (el parámetro 1 es una cadena) alrededor de la llamada como lo sugiere Tudor. –

+0

¿Puede intentar registrar para qué valores de 'Parameter1' se produce el bloqueo? ¿Puedes ver algún patrón? – Tudor

+0

He codificado el código exacto que se muestra arriba, codificando la asignación a una variable de cadena inicializándola con "abcde" y asignando esa variable a Parameter1 probándola a través de if (Parámetro1 es una cadena) y todavía funciona bien en Visual Studio pero falla afuera de VS (a veces). –

Respuesta

5

Porque obj as string y obj.ToString() no son lo mismo. El primero es un intento de conversión (algo así como (string)obj, pero que devuelve null al fallar), mientras que los segundos son una llamada a método que devuelve una representación de cadena del objeto.

Prácticamente puede obtener la representación de cadena de cualquier objeto independientemente de si es compatible con la cadena como tipo, pero el lanzamiento fallará si no son compatibles.

ejemplo sencillo:

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! 
+0

He actualizado desde entonces mi código de muestra para mostrar que el parámetro 1 siempre contiene un objeto de cadena válido. También tengo problemas con la aleatoriedad del error y el hecho de que no hay ningún problema al ejecutar Visual Studio. –

+0

@RichardBousman: ¿Así que está seguro de que 'Parameter1' siempre es una cadena válida? Pude ver que la situación que mencionaste sucedió en caso de que a veces pases un hilo no por error, de modo que 'como cadena' falla, pero' ToString' no. – Tudor

+0

Sí. Si no fuera así, creo que 1) fallaría siempre 2) fallaría en Visual Studio. El parámetro se verifica varias veces antes de este punto. El código al que se hace referencia arriba está en una DLL. El código está en una DLL administrada. La cadena se pasa originalmente a la DLL administrada desde una DLL de C++ no administrada. –

2

Parameter1.ToString() rendirá cualquier objeto .NET para una cadena (es decir, ejemplo de System.String). Parameter1 as string devolverá null si Parameter1 es nulo o si no es una instancia de System.String. Si es una clase que envuelve una cadena en lugar de realmente siendo, terminará con null.

Ninguno funcionará en todos los casos, por supuesto. Si tiene una instancia de System.String que es null, entonces Parameter1 as string devolverá correctamente null, mientras que Parameter1.ToString() arrojaría NullReferenceException.

Un enfoque seguro sería: Convert.ToString(Parameter1).

+0

Gracias por la respuesta. Desde entonces, actualicé la publicación original para mostrar que el parámetro 1 siempre es una cadena válida. –

0

Parameter1 as string podría pensarse como

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

donde .ToString() es

string foo = Parameter1.ToString(); 

El hecho de que no es directamente Parámetro1 moldeable a una cadena es el reson por ello fallar.

Cuestiones relacionadas