2010-11-14 16 views
13

Acceso a un miembro en el Formulario puede causar una excepción de tiempo de ejecución, ya que es un campo de un Marshal por caso clase de referenciaAcceso a un miembro en el Formulario puede causar una excepción de tiempo de ejecución debido a que es un campo de una clase Marshal por referencia

Sé lo que es esta advertencia y sé cómo resolverla.

Mi pregunta es por qué podría esto causar un error de tiempo de ejecución?

+0

¿Cuál es el contexto en el que aparece esta advertencia? –

Respuesta

23

Usted probablemente está hablando CS1690 advertencia, código de repro:

public class Remotable : MarshalByRefObject { 
    public int field; 
} 
public class Test { 
    public static void Run() { 
     var obj = new Remotable(); 
     // Warning CS1690: 
     Console.WriteLine(obj.field.ToString()); 
    } 
} 

En un escenario de interacción remota, el método Test.Run trabajará con un proxy del objeto Remotable. Crear un proxy para una propiedad, método o evento no es un gran problema, solo es cuestión de crear una tabla de métodos que contenga los sustitutos. Los campos son un problema, sin embargo, no hay nada que 'enganchar'. Para un MBRO, el compilador JIT ya no genera código para acceder al campo directamente, sino que inyecta una llamada a un método auxiliar integrado en el CLR, JIT_GetField32() en este caso.

Ese ayudante comprueba si el objeto es un proxy y utiliza la fontanería remota para obtener el valor remoto si ese es el caso. O simplemente accede al campo directamente si no es así. Sin embargo, realizar la llamada ToString() requiere que el valor esté encuadrado. Eso es un problema, el boxeo aísla el valor del proxy. No hay forma de garantizar que el valor en caja sea siempre una copia exacta del valor remoto. Llamar a JIT_GetField32() de nuevo cada vez que el método ToString() usa el valor para formatear la cadena no es posible.

La solución para CS1690 es simple, más allá de envolver el campo con una propiedad, simplemente copie el valor del campo en una variable local. Ahora está claro que el código está trabajando con una copia y nunca hay sorpresa, por lo que el compilador no tendrá que emitir una advertencia.

public static void Run() { 
    var obj = new Remotable(); 
    var value = obj.field; 
    Console.WriteLine(value.ToString());  // No warning 
} 
+1

Muchas gracias. Acabo de recibir esta advertencia, y tuve la suerte de que tuvieras una respuesta aquí. –

+0

¿Quiso escribir 'var i = obj.campo; Console.WriteLine (i.ToString()); ¿? –

0

Si el otro lado del objeto calculado ha muerto, generará un error de tiempo de ejecución que indica que el objeto al que se hace referencia ya no existe.

3

Además de la sugerencia de @ Hans-passant, creo que otra forma útil para solucionar esta advertencia es por convertir su campo en una propiedad.

public class Remotable : MarshalByRefObject { 
    public int field; 
} 

podrían convertirse en

public class Remotable : MarshalByRefObject { 
    public int field { get; set } 
} 

y ya no obtener ninguna advertencia! (Hans Passant ya tiene una excelente explicación para esto, vea his post)

Obviamente, no siempre puede modificar el objeto con el que está trabajando (ejemplo: WinForms donde se generan los campos) por lo que podría tener que recurrir a usando una variable temporal.

0

O puede escribir:

var obj = new Remotable(); 

Console.WriteLine(((int) obj.field).ToString());  // No warning 

Aquí tomar su propia responsabilidad de ese molde (unboxing).

Cuestiones relacionadas