С этим событием .NET можно ли передавать этот экземпляр IList? - PullRequest
4 голосов
/ 23 сентября 2010

У меня есть следующий код: -

while (....)
{
    var foo = DoTheFooShakeShakeShake(..);
    foos.Add(foo); // foos is an IList<Foo>, btw and is new'd, above.

    if (foos.Count % 100 == 0)
    {
        var e = new CustomFooEventArgs { UserId = whatever, Foos = foos };
        OnFooPewPew(this, e);
        foos.Clear();
    }
}

// We still might have some foo's left over.. so send em off also.
// Excuse the woeful var names, below.
var e2 = new CustomFooEventArgs { UserId = whatever, Foos = foos };
OnFooPewPew(this, e2);

Итак, я беру все фу на некоторое время / цикл. Затем каждые 100 foo я запускаю событие, которое передает список foo подписчику. Затем я очищаю этот список foos. Как только цикл завершен, я запускаю все оставшиеся подписчики.

Итак, если я инициирую событие, которое содержит список foo's ... и затем я ОЧИСТЮ этот список ... это будет означать, что подписчик может получить этот список, который теперь пуст? Должен ли я передать копию списка ... и затем очистить исходный список?

Ответы [ 4 ]

5 голосов
/ 23 сентября 2010

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

Мало того, что вы можете испортить подписчика, он может связываться с вами , поскольку они могут изменять список и влиять на ваш собственный процесс.

Если это не желаемое поведение (и я не могу думать, что это так), вы захотите отправить даже не копию, а IEnumerable<Foo> или ReadOnlyCollection<Foo>. Потому что даже если вы отправите копию, если у вас будет несколько подписчиков, они все получат одну и ту же копию, поэтому их мутации все равно будут разрушать друг друга.

2 голосов
/ 23 сентября 2010

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

2 голосов
/ 23 сентября 2010

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

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

1 голос
/ 23 сентября 2010

Я бы предпочел сделать это с комментариями, но у меня нет репутации: -)

Параноидальное расширение Ответ Энтони , где вы не можете контролироватьполучатели, чтобы убедиться, что копия списка, которую вы раздаете, является ReadOnlyCollection<Foo> (*).Если вы просто скопируете свой список как другую List<Foo> или другую изменяемую коллекцию, даже если CustomFooEventArgs определяет Foos как неизменяемый интерфейс, такой как IEnumerable<Foo>, особенно подлый получатель может привести Foos к List<Foo> и изменить его.

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

(*) Я бы, вероятно, определил его как IEnumerable<Foo> в CustomFooEventArgs, хотя факт использования ReadOnlyCollection<Foo> является деталью реализации IMHO.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...