Подтвердить что ты не робот

Являются ли аргументы событий переданными по ссылке или значению в С#?

Довольно простой вопрос (я думаю), но, похоже, я уже не вижу ответа. Я знаю, что некоторые значения передаются через значение (например, int и long), а другие передаются по ссылке (например, строки), когда вы передаете их в функции.

В моей программе я использую фоновый рабочий, так что графический интерфейс не блокируется, когда мы делаем длинный процесс в фоновом режиме. Мне нужно передать данные обратно в поток пользовательского интерфейса из другого файла, поэтому я использовал для этого события. Теперь мне нужно отправить список массивов строк обратно в поток GUI, чтобы обработать его, и я волнуюсь, как это будет обрабатываться. В основном, в рабочем потоке у меня есть цикл, который заполнит список, отправит его обратно в GUI через обработчик событий, а затем очистит его, чтобы он мог заполнить его на следующем проходе через цикл и начать заново.

Я беспокоюсь, что, когда я это делаю, если список передается по ссылке, то в потоке пользовательского интерфейса я бы подумал, что он будет очищен в середине чтения, так как рабочий поток все равно будет очищать его в фоновом режиме. В этом случае переход будет гораздо предпочтительнее, и я могу найти способы его принудительного (копирование в некоторый массив держателей или добавление мьютекса или что-то в этом роде), но я подумал, что было бы хорошо знать, передаются ли аргументы события через ссылка или значение в целом, или это то же самое, что и методы, и оно будет передавать их, поскольку аргументы обычно передаются?

4b9b3361

Ответ 1

Я знаю, что некоторые значения передаются через значение (например, int и long), а другие передаются по ссылке (например, строки), когда вы передаете их функциям.

Неа. По умолчанию все передается по значению - но когда вы используете ссылочные типы, "все" является ссылкой. Эта ссылка передается по значению. Это не то же самое, что передавать по ссылке. Подробнее см. мою статью о передаче параметров.

Аргументы событий точно совпадают - любые ссылки передаются по значению, если соответствующий делегат не использует параметры out или ref.

EDIT: Итак, чтобы решить вашу проблему: да, если аргумент вашего события изменен и вы собираетесь действовать по другому потоку, сначала нужно создать копию... или, альтернативно, передать существующую ссылку, а затем создать новый (пустой) список в вашем рабочем потоке.

Ответ 2

Аргументы по умолчанию передаются по значению. Однако, в зависимости от их типа, они могут быть значениями или ссылками на фактические значения, с которыми вы работаете.

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

Теперь при передаче по значению ничего особенного в аргументах событий нет; копируются ли значения или только их ссылки полностью зависят от их типа. Итак, как вы сказали, аргументы int и long (и некоторые другие типы struct) являются типами значений, в то время как другие, такие как string (и любые экземпляры классов), являются ссылочными типами.

Обратите внимание, что истинная передача по ссылке возможна и в С#, но для этого требуется ref ключевое слово.

Ответ 3

В стандартном шаблоне событий есть две ссылки, переданные в:

 void FormClosing(object sender, FormClosingEventArgs e) { ... }

эти две ссылки передаются "по значению", использование, например, sender = null не будет иметь эффекта вне метода обработки.

Но вы можете легко передать значение обратно:

void FormClosing(object sender, FormClosingEventArgs e)
{
    ...
    e.Cancel = true;  // this will pass back to the caller
}

Ответ 4

Аргументы события передаются в соответствии с типом аргументов и подписи делегата обработчика события (в, из или ref) - если это класс, то копия ссылки передается, если она является структурой, тогда копия значения передается (если подпись не указана или не указана).

Аргументы события обычно являются классом (обычно наследуются от EventArgs) и часто используются для возврата таких значений, как eventArgs.DoCancel, в вызывающего абонента.