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

StackOverflow https://stackoverflow.com/questions/4178576

Pregunta

Acceso a un miembro en el formulario puede causar una excepción de tiempo de ejecución porque es un campo de una clase Marshal por referencia

Yo sé lo que es esta advertencia y sé cómo solucionarlo.

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

¿Fue útil?

Solución

Usted probablemente está hablando de advertencia CS1690, 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 comunicación remota, el método Test.Run trabajará con un proxy del objeto Remotable. La construcción de un proxy para una propiedad, método o evento no es un gran problema, sólo es cuestión de crear un MethodTable que contiene los sustitutos. Los campos son un problema, sin embargo, no hay nada que 'gancho'. Para una MBRO, el compilador JIT ya no genera código para el acceso al campo directamente, se inyecta una llamada a un método de ayuda integrado en el CLR, JIT_GetField32 () en este caso.

que los cheques de ayuda si el objeto es un proxy y utiliza la tubería de comunicación remota para obtener el valor remoto si ese es el caso. O simplemente accede al campo directamente si no lo es. Hacer la llamada ToString () requiere, sin embargo el valor de guardarlos en cajas. Eso es un problema, el boxeo aísla el valor del proxy. No hay manera de garantizar que el valor en caja es siempre una copia exacta del valor remoted. Llamando JIT_GetField32 () de nuevo cada vez que el método ToString () utiliza el valor para dar formato a la cadena no es posible.

La solución para CS1690 es simple, más allá de envolver el campo con una propiedad, simplemente copia el valor del campo en una variable local. Ahora bien, es claro que el código está trabajando con una copia y nunca hay una 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
}

Otros consejos

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ía convertirse

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

y ya no recibe ninguna advertencia! (Hans Passant ya tiene una explicación excelente para esto, vea su puesto )

Obviamente, no siempre se puede alterar el objeto que se está trabajando. (Ejemplo: WinForms donde se generan los campos para usted) por lo que puede que tenga que replegará para usar una variable temporal

Si el otro lado del objeto formateado ha muerto, arrojará un error de ejecución que indica que el objeto referenciado no existe más.

O puede escribir:

var obj = new Remotable();

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

A continuación, se toma su propia responsabilidad de ese molde (unboxing).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top