none
Почему изменяется внешний аргумент byVal через процедуру RRS feed

  • Pergunta

  • Добрый вечер! Необходима помощь мудрецов. Не могу понять почему такое происходит... 

    Есть класс. При его создании обработчик кидается на событие Message

        Public UID As Integer
    
        Private Sub onMessage(Data As Concurrent.ConcurrentDictionary(Of String, Integer))
            If Data("UID") = UID Then
                Data.TryRemove("UID", Nothing)
                RemoveHandler General.Message, AddressOf onMessage
            End If
        End Sub

    Каждому классу присваивается свой свой уникальный номер UID.

    Data в сообщении состоит из номера класса (кому адресовано) и других данных.

    Создаем 50 классов. И в отдельном потоке вызываем событие Message со случайными данными и номерами классов от 1 до 50.

    И тут получаем ошибку, что нет ключа UID в Data.

    Если записать какие данные проверяет класс и какой класс выдает ошибку получается следующее:


    ... UID=37 FCE7557B47F6A2E5CF60C0A41CEF582F UID=38 D77A9E88E68C6CFDEAC253A71968ED05 UID=39 F11CF753E4CE4C51630CC7C2B49AFE4C UID=40 2BCC6B0F35AF7DFEACA02BB05CF221F2 'Ключ UID совпадает с классом #40. Удаляется ключ UID из Data ERR 42 2BCC6B0F35AF7DFEACA02BB05CF221F2 'тут ключа UID уже нет. Ошибку выдал класс #42 UID=41 22B1B97EFCF1BB329C722D2686985769 UID=42 FA20FE2EEF8DB8286898750FCED121E4 UID=43 91343FC10A2CB3111D39FFE360D1C928 UID=44 8D7FBA4D9BD10D3B96B1CF31326A296A UID=45 22AF3A6DAB0E0F17F64ED76EAA1E8991 UID=46 CFD80181E625C04DC805E7AA1ADDB8A4 UID=47 1FA79A74ECFEE0798DE5FC9C1A72086F UID=48 BB033FD8A351BE8AF2CDC5F7E67BF5CA UID=49 C91CE8D3B31583D3A2429E6047CDE056 ERR 50 C91CE8D3B31583D3A2429E6047CDE056 ERR 51 C91CE8D3B31583D3A2429E6047CDE056 ERR 52 C91CE8D3B31583D3A2429E6047CDE056 ERR 53 C91CE8D3B31583D3A2429E6047CDE056 UID=52 0B818EF8ACB528EC4B5DB4AA0D79240E UID=53 F6C7D0EFABACAAC8C98E25489648C22E UID=50 91CAB0D735B283C243E088FEB6C40571 UID=51 E016FF9201DAEF53EF4E9E88A2671BCE

    На примере видим:

    Когда класс UID 40 видит свой номер, все нормально - он его удаляет из Data. Но данные события проверяют все остальные классы. И класс 42 начал проверять после того, как 40 удалил ключ UID из Data. Поэтому выдал ошибку. 

    Но почему? Data объявлена как ByVal. Данные должны меняться только внутри обработчика класса. для остальных они должны быть такими, какие были изначально. 

     

    segunda-feira, 22 de novembro de 2021 23:03

Respostas

  • Что то мне подсказывает что передача всех reference type (включая ConcurrentDictionary) всегда производится по ссылке. ByVal касается только value types, с ними есть возможность выбора по ссылке или по значению.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    terça-feira, 23 de novembro de 2021 07:54
    Moderador