Комментарии 27
А разве нельзя так, без Volatile, Read, Invoke
?
public event EventHandler Foo = delegate {}
public void OnFoo()
{
Foo(this, EventArgs.Empty);
}
?
Да, можно — это решит NullReferenceException, но:
1. Это не очень красиво.
2. Используем не самый последний список подписчиков.
1. Это не очень красиво.
2. Используем не самый последний список подписчиков.
1. Это не очень красиво.
Почему? По-моему красивее, чем описанные в статье варианты, в т.ч. c новым оператором.
2. Используем не самый последний список подписчиков.
А разве вариант с?.. решает эту проблему?
НЛО прилетело и опубликовало эту надпись здесь
> Минус данного подхода в том, что метод расширения придется писать для каждого типа обработчика
а дженерики нам на что даны?
а дженерики нам на что даны?
public static void Raise<T>(this EventHandler<T> evt, object sender, T args) where T : EventArgs
НЛО прилетело и опубликовало эту надпись здесь
А как же точка под вопросительным знаком? ?.
НЛО прилетело и опубликовало эту надпись здесь
Да, в последних релизах C# старается брать что-то от динамических и функциональных языков, и я считаю, что это здорово. Например, string interpolation в C# 6 хорош (взятый из Ruby).
НЛО прилетело и опубликовало эту надпись здесь
В видео вот в этом курсе разработчики употребляют название Elvis-operator mva.microsoft.com/en-US/training-courses/developer-productivity-what-s-new-in-c-6-8733
НЛО прилетело и опубликовало эту надпись здесь
Мне не понятно только одно, почему все постоянно так озадачены тем, что Event?.Invoke использует не наисвежайшую версию делегата?
И да не один из вышеописанных способов не гарантирует получение наисвежайшей версии, между вызовами Volatile.Read и Interlocked.CompareExchange и непосредственно вызовом делегата, оригинал может быть изменен ровно с такой же вероятностью как и без них.
Если нужна гарантия вызова актульной версии, поможет только блокировка.
И да не один из вышеописанных способов не гарантирует получение наисвежайшей версии, между вызовами Volatile.Read и Interlocked.CompareExchange и непосредственно вызовом делегата, оригинал может быть изменен ровно с такой же вероятностью как и без них.
Если нужна гарантия вызова актульной версии, поможет только блокировка.
Мне кажется, в 99.9% случаев достаточно просто вызвать текущий список и никакой проблемы не будет, чем добавлять локи и получать проблемы в производительности. Но представлять как все работает — полезно для разработчика.
А откуда пошло название «Элвис-оператор»?
Я вот что-то не могу найти сходства с Элвисом
Я вот что-то не могу найти сходства с Элвисом
Вопросительный знак — как прическа. Вроде бы, поэтому.
en.wikipedia.org/wiki/Elvis_operator
en.wikipedia.org/wiki/Elvis_operator
Имхо вся эта возня как верно заметили решается пустым делегатом с ничтожной потерей производительности. Намного больше проблем может возникнуть, если мы сохранили список с делегатами, а пока мы их вызываем, делегат из конца списка отписался и освободил ресурсы.
Никакой C# 6.0 тут нас не спасет (равно как и пустой делегат, к слову), так что нужно просто смириться с тем, что вызывающему коду нужно быть очень аккуратным в работе с подпиской/отпиской.
using System;
using System.Threading;
namespace ConsoleApplication25
{
class Program
{
static void Main(string[] args)
{
var example = new Example();
for (int i = 0; i < 10; i++)
{
int j = i;
example.Foo += (sender, eventArgs) =>
{
Thread.Sleep(100);
Console.WriteLine(j);
};
}
using (var disposable = new MyDisposable())
{
example.Foo += (sender, eventArgs) => disposable.Foo();
new Thread(() => example.OnFoo()).Start();
}
Console.WriteLine("Waiting...");
Console.ReadKey();
}
}
class Example
{
public event EventHandler Foo;
public void OnFoo()
{
EventHandler handler = Foo;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
class MyDisposable : IDisposable
{
private bool _disposed;
public void Dispose()
{
_disposed = true;
}
public void Foo()
{
if (_disposed)
throw new ObjectDisposedException("MyDisposable");
Console.WriteLine("Hello world!");
}
}
}
Никакой C# 6.0 тут нас не спасет (равно как и пустой делегат, к слову), так что нужно просто смириться с тем, что вызывающему коду нужно быть очень аккуратным в работе с подпиской/отпиской.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Вызываем обработчики событий потокобезопасно без лишнего присваивания в C# 6