Accesso dell'utente su modulo può causare un'eccezione di runtime perché è un campo di una classe maresciallo-by-reference

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

Domanda

  

Accesso un membro su modulo può causare un'eccezione di runtime perché   è un campo di una classe maresciallo per riferimento

So cosa questo avvertimento è e so come risolverlo.

La mia domanda è perché potrebbe questo causa un errore di runtime?

È stato utile?

Soluzione

Probabilmente si sta parlando di avviso CS1690, il codice 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());
    }
}

In uno scenario di servizi remoti, il metodo Test.Run lavorerà con un proxy dell'oggetto Remotable. Costruire un proxy per una proprietà, metodo o evento non è un gran problema, solo una questione di creare un MethodTable che contiene i sostituti. I campi sono un problema, tuttavia, non c'è niente da 'gancio'. Per un MBro, il compilatore JIT non genera il codice per accedere al campo direttamente, si inietta una chiamata a un metodo di supporto integrato nel CLR, JIT_GetField32 () in questo caso.

che controlla helper se l'oggetto è un proxy e utilizza l'impianto idraulico remoting per ottenere il valore remota se questo è il caso. O semplicemente accede al campo direttamente, se non lo è. Effettuare la chiamata ToString () tuttavia richiede il valore da scatola. Questo è un problema, il pugilato isola il valore dal proxy. Non v'è alcun modo per garantire che il valore boxed è sempre una copia fedele del valore telecomandato. Chiamando JIT_GetField32 () di nuovo quando il metodo ToString () utilizza il valore per formattare la stringa non è possibile.

La soluzione per CS1690 è semplice, al di là avvolgendo il campo con una proprietà, basta copiare il valore del campo in una variabile locale. Ora è chiaro che il codice sta lavorando con una copia e non c'è mai una sorpresa in modo che il compilatore non dovrà emettere un avvertimento.

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

Altri suggerimenti

In aggiunta al suggerimento da @ Hans-passant, penso che un altro modo utile per risolvere questo avviso è da trasformare il campo in una proprietà.

public class Remotable : MarshalByRefObject {
    public int field;
}

potrebbe diventare

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

e si ottiene più alcun avvertimenti! (Hans Passant ha già una spiegazione eccellente per questo, vedi suo posto )

Ovviamente, non si può sempre modificare l'oggetto che si sta lavorando. (Esempio: WinForms dove i campi sono generati per voi) così si potrebbe avere per il fallback per utilizzare una variabile temporanea

Se l'altro lato dell'oggetto marshalling è morto, si getterà un errore di runtime che indica che l'oggetto di riferimento non esiste più.

In alternativa, è possibile scrivere:

var obj = new Remotable();

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

Qui si prende la propria responsabilità per quel cast (unboxing).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top