Не используйте разделители регулярных выражений:
name = Regex.Replace(name, @"\W", "");
В C # вы не можете использовать разделители регулярных выражений, поскольку синтаксис объявления обычного выражения отличается от синтаксиса PHP, Perl или JavaScript или других, которые поддерживают <action>/<pattern>(/<substituiton>)/modifiers
regex.
Просто, чтобы избежать путаницы в терминологии: встроенные модификаторы (принудительный поиск без учета регистра, многострочный, одинарный, многословный и другие режимы), безусловно, поддерживаются и могут использоваться вместо соответствующих флагов RegexOptions
(хотя число возможных флагов RegexOptions
выше, чем число встроенных модификаторов). Тем не менее, regex delimiters вообще не влияют на шаблон регулярного выражения, они являются лишь частью синтаксиса объявления и не влияют на сам шаблон. Скажем, они являются просто альтернативой для ;
или строк, разделяющих строки новой строки.
В C # разделители регулярных выражений не нужны и, следовательно, не поддерживаются. Perl-стиль s/\W//g
будет записан как var replaced = Regex.Replace(str, @"\W", string.Empty);
. И так далее.
Реализация по умолчанию компилятора C# добавления обработчика событий звонит Delegate.Combine
, в то время как удаление обработчика событий звонит Delegate.Remove
:
Fire = (MyDelegate) Delegate.Remove(Fire, new MyDelegate(Program.OnFire));
реализация Платформы Delegate.Remove
не смотрит эти MyDelegate
сам объект, но в методе делегат обращается к (Program.OnFire
). Таким образом совершенно безопасно создать новое MyDelegate
объект при отмене подписки существующего обработчика событий. Из-за этого компилятор C# позволяет Вам использовать синтаксис стенографии (который генерирует точно тот же код негласно) при добавлении/удалении обработчиков событий: можно опустить new MyDelegate
часть:
Fire += OnFire;
Fire -= OnFire;
, Когда последний делегат удален из обработчика событий, Delegate.Remove
пустой указатель возвратов. Как Вы узнали, важно проверить событие по пустому указателю прежде, чем повысить его:
MyDelegate handler = Fire;
if (handler != null)
handler("Hello 3");
Это присвоено временной локальной переменной для защиты от возможного состояния состязания с отказывающимися от подписки обработчиками событий на других потоках. (См. мое сообщение в блоге для получения дополнительной информации о потокобезопасности присвоения обработчика событий к локальной переменной.) Другой способ защитить от этой проблемы состоит в том, чтобы создать пустого делегата, который всегда подписывается; в то время как это использует немного больше памяти, обработчик событий никогда не может быть пустым (и код может быть более простым):
public static event MyDelegate Fire = delegate { };
Необходимо всегда проверять, нет ли у делегата целей (его значение является пустым) прежде, чем запустить его. Как сказано прежде, один способ сделать это должно подписаться с пустым анонимным методом, который не будет удален.
public event MyDelegate Fire = delegate {};
Однако это - просто взлом для ухода от NullReferenceExceptions.
Просто проверка, является ли делегат пустым перед вызовом, не ориентирована на многопотоковое исполнение, поскольку другой поток может вычеркнуть из списка после пустой проверки и создания его пустой указатель при вызове. Существует другое решение, должен скопировать делегата во временную переменную:
public event MyDelegate Fire;
public void FireEvent(string msg)
{
MyDelegate temp = Fire;
if (temp != null)
temp(msg);
}
, К сожалению, JIT-компилятор может оптимизировать код, устранить временную переменную и использовать исходного делегата. (согласно Juval Lowy - Программирование Компонентов.NET)
Так для предотвращения этой проблемы Вы могли использовать метод, который принимает делегата как параметр:
[MethodImpl(MethodImplOptions.NoInlining)]
public void FireEvent(MyDelegate fire, string msg)
{
if (fire != null)
fire(msg);
}
Примечание, которые без MethodImpl (NoInlining) приписывают JIT-компилятор, могло встроить метод, делающий его бесполезный. Так как делегаты неизменны, эта реализация ориентирована на многопотоковое исполнение. Вы могли использовать этот метод как:
FireEvent(Fire,"Hello 3");