ein Element auf dem Formular Zugriff kann eine Laufzeitausnahme verursachen, da es sich um ein Feld eines Marshal-by-reference Klasse ist

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

Frage

ein Mitglied Zugriff auf Formular kann eine Laufzeitausnahme, weil es dazu führen, ist ein Feld einer Marshal-by-Referenzklasse

Ich weiß, was diese Warnung ist und weiß, wie es zu lösen.

Meine Frage ist, warum konnte diese Ursache ein Laufzeitfehler?

War es hilfreich?

Lösung

Sie sprechen wahrscheinlich über CS1690 Warnung, repro Code:

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 einem Szenario remoting, die Test.Run Methode wird mit einem Proxy des Remotable-Objekt arbeiten. Der Aufbau ein Proxy für eine Eigenschaft, Methode oder Ereignis ist nicht viel von einem Problem, nur eine Sache von MethodTable zu schaffen, die den Ersatz enthält. Die Felder sind ein Problem, aber es gibt nichts zu ‚Haken‘. Für eine MBRO erzeugt der JIT-Compiler nicht mehr Code den Zugriff auf das Feld direkt, sondern einen Aufruf an eine Hilfsmethode in die CLR, JIT_GetField32 () in diesem Fall gebaut einspritzt.

Dass Helfer überprüft, ob das Objekt ein Proxy und verwendet die remoting Sanitär- den Remote-Wert zu erhalten, wenn das der Fall ist. Oder nur greift auf das Feld direkt, wenn dies nicht der Fall. Making the ToString () Aufruf erfordert jedoch den Wert eingerahmt werden. Das ist ein Problem, Boxen den Wert aus dem Proxy-Isolaten. Es gibt keinen Weg, um sicherzustellen, dass der Box-Wert immer eine genaue Kopie des remoted Wertes. Der Aufruf JIT_GetField32 () erneut aufgerufen, wenn die Methode ToString () den Wert verwendet die Zeichenfolge zu formatieren ist nicht möglich.

Die Abhilfe für CS1690 ist einfach, mit einem Grundstück, das Feld über Verpackung, kopieren Sie einfach den Feldwert in einer lokalen Variablen. Nun ist es klar, dass der Code mit einer Kopie arbeitet und es gibt nie eine Überraschung, so wird der Compiler keine Warnung abgeben müssen.

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

Andere Tipps

Neben den Vorschlag von @ hans-passant, glaube ich, eine andere nützliche Möglichkeit, diese Warnung zu beheben, ist von Ihrem Feld in eine Eigenschaft drehen.

public class Remotable : MarshalByRefObject {
    public int field;
}

könnte werden

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

und Sie nicht länger werden alle Warnungen! (Hans Passant hat bereits eine ausgezeichnete Erklärung hierfür finden Sie unter seinen Posten )

Natürlich können Sie nicht immer verändern das Objekt, das Sie arbeiten. (Beispiel: WinForms, wo die Felder für Sie generieren), so dass Sie mit einer temporären Variablen zu Rückfall haben könnten

Wenn die andere Seite des vermarshallten Objekts gestorben ist, wird es einen Laufzeitfehler wirft die besagt, dass das referenzierte Objekt nicht mehr existiert.

Sie können auch schreiben:

var obj = new Remotable();

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

Hier nehmen Sie Ihre eigene Verantwortung für diese Besetzung (Unboxing).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top