Доступ к участнику в форме может вызвать исключение времени выполнения, потому что это поле маршала за ссылками

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

Вопрос

Доступ к участнику в форме может вызвать исключение времени выполнения, потому что это поле маршала за ссылками

Я знаю, что это за предупреждение, и знаю, как его решить.

Мой вопрос: почему это может вызвать ошибку времени выполнения?

Это было полезно?

Решение

Вы, вероятно, говорите о предупреждении CS1690, 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());
    }
}

В удаленном сценарии метод Test.Run будет работать с прокси -дистанционным объектом. Создание прокси для свойства, метода или события не является большой проблемой, просто вопрос создания метода, который содержит заменители. Поля являются проблемой, однако, нет ничего, чтобы «зацепить». Для MBRO компилятор JIT больше не генерирует код, чтобы получить непосредственное доступ к полю, он вводит вызов вспомогательному методу, встроенному в CLR, JIT_GETFILDE32 () в данном случае.

Этот помощник проверяет, является ли объект прокси и использует удаленную сантехнику, чтобы получить удаленное значение, если это так. Или просто обращается к поле напрямую, если нет. Тем не менее, создание вызова toString () требует, чтобы значение было в коробке. Это проблема, бокс изолирует значение от прокси. Нет никакого способа убедиться, что штучное значение всегда точная копия удаленного значения. Вызов jit_getfield32 () снова всякий раз, когда метод toString () использует значение для форматирования строки, невозможно.

Обходной путь для CS1690 прост, помимо обертывания поля с свойством, просто скопируйте значение поля в локальной переменной. Теперь кристально ясно, что код работает с копией, и никогда не бывает сюрприза, поэтому компилятору не придется издавать предупреждение.

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

Другие советы

В дополнение к предложению от @Hans-Passant, я думаю, что еще один полезный способ исправить это предупреждение-превратить ваше поле в свойство.

public class Remotable : MarshalByRefObject {
    public int field;
}

мог стать

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

И вы больше не получаете никаких предупреждений! (Hans Passant уже имеет превосходное объяснение этого, см. его пост)

Очевидно, что вы не всегда можете изменить объект, с которым вы работаете (пример: Winforms, где поля генерируются для вас), поэтому вам, возможно, придется отступить для использования временной переменной.

Если другая сторона маршалированного объекта умерла, это принесет ошибку времени выполнения, в которой говорится, что указанный объект больше не существует.

Или вы можете написать:

var obj = new Remotable();

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

Здесь вы берете свою ответственность за этот актерский состав (распаковка).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top