Accès à un membre sur le formulaire peut provoquer une exception d'exécution, car il est un champ d'un maréchal par référence classe

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

Question

  

Accès à un membre sur le formulaire peut provoquer une exception d'exécution parce qu'il   est un champ d'une classe maréchal par référence

Je sais ce que cet avertissement est et de savoir comment le résoudre.

Ma question est pourquoi pourrait-il provoquer une erreur d'exécution?

Était-ce utile?

La solution

Vous parlez probablement d'avertissement CS1690, le code 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());
    }
}

Dans un scénario d'accès distant, la méthode Test.Run travaillera avec un proxy de l'objet Remotable. Construire une procuration pour une propriété, une méthode ou un événement n'est pas un gros problème, juste une question de la création d'un MethodTable qui contient les substituts. Les champs sont un problème cependant, il n'y a rien à « crochet ». Pour un MBro, le compilateur JIT ne génère plus de code pour accéder au champ directement, il injecte un appel à une méthode d'assistance intégrée dans le CLR, JIT_GetField32 () dans ce cas.

Que aide vérifie si l'objet est un proxy et utilise la plomberie Remoting pour obtenir la valeur à distance si tel est le cas. Ou les accès tout le champ directement si ce n'est pas. Faire l'appel ToString () nécessite cependant la valeur à boxed. C'est un problème, la boxe isole la valeur du proxy. Il n'y a aucun moyen de faire en sorte que la valeur est boxed toujours une copie exacte de la valeur déportée. Calling JIT_GetField32 () à chaque fois que la méthode ToString () utilise la valeur pour formater la chaîne n'est pas possible.

La solution de contournement pour CS1690 est simple, au-delà de l'emballage sur le terrain avec une propriété, il suffit de copier la valeur du champ dans une variable locale. Maintenant, il est clair que le code fonctionne avec une copie et il n'y a jamais une surprise si le compilateur ne doit émettre un avertissement.

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

Autres conseils

En plus de la suggestion de @ hans-passant, je pense qu'une autre façon utile de corriger cet avertissement est en transformant votre champ dans une propriété.

public class Remotable : MarshalByRefObject {
    public int field;
}

pourrait devenir

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

et vous ne recevez plus aucun avertissement! (Hans a déjà une Passant explication excelent pour cela, voir son poste )

De toute évidence, vous ne pouvez pas toujours modifier l'objet que vous travaillez. (Exemple: WinForms où les champs sont générés pour vous) afin que vous pourriez avoir à l'aide d'un repli à variable temporaire

Si l'autre côté de l'objet est mort marshalé, il lancera une erreur d'exécution indiquant que l'objet référencé n'existe plus.

Ou vous pouvez écrire:

var obj = new Remotable();

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

Ici, vous prenez votre responsabilité de CAST (unboxing).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top