- Событие нельзя объявить свойством, только полем. Однако событие поддерживает определение своих методов подписки и отписки (add и remove) в стиле свойств.
- Реализация подписки и отписки на событие потокобезопасна (речь идёт о штатных методах add и remove).
- Полю события нельзя присвоить null вне другого класса. Вообще, стороннему коду нельзя ничего сделать с полем события кроме как подписаться или отписаться. Для этого используются операторы += и -=, которые транслируются в вызов add и remove. Оператор = к событиям не применим.
- Запускать событие напрямую можно только в том классе, в котором оно объявлено. Даже в потомках нельзя. Однако это можно сделать через метод-обёртку.
Программирование
понедельник, 3 марта 2014 г.
Сравнение: event vs delegate
пятница, 28 февраля 2014 г.
Ошибка в переводном 4-м издании "CLR via C#" Рихтера
В примере кода, который находится в разделе "Уведомление о событии, безопасное в отношении потоков" (с. 291), использован устаревший метод Thread.VolatileRead() вместо Volatile.Read().
В оригинальном издании всё правильно — везде используется Volatile.Read(). В разделе упоминания этих методов чередуются, так что судя по всему это результат "недоправки" листингов с предыдущих изданий. Больше нигде в книге Thread.VolatileRead() не упоминается. Про Thread.VolatileRead() и Volatile.Read() можно начать читать отсюда.
понедельник, 10 февраля 2014 г.
Доступ к непубличным экземплярным полям класса
class PrivateFieldsAccess
{
private int privateField;
protected int protectedField;
public PrivateFieldsAccess(PrivateFieldsAccess instance)
{
privateField = instance.privateField;
protectedField = instance.protectedField;
}
}
Модификаторы доступа определяют доступ к членам класса, а не экземпляра. Другими словами, ограничение доступа к членам класса служит для инкапсуляции и снижения зависимости между кусками кода, а не снижения зависимости объектов в памяти во время выполнения.
пятница, 19 апреля 2013 г.
Ловушки при использовании Response.Filter
ASP.NET позволяет через свойство HttpResponse.Filter выполнять манипуляции с контентом перед отправкой его клиенту. Под контентом понимается html-разметка, css-стиль, js-код и вообще любые данные, отправляемые веб-сервером в ответ на запрос. Для чего это нужно? Например, для замены в теле ответа одного текста на другой. Подробно расписывать как это делать я не буду, а покажу очень важные особенности, которые необходимо учитывать при реализации продобного рода фильтров.
Первая ловушка — отдаваемый сервером контент разбивается на порции. Приведу типичный код, встречающийся на просторах интернета, который заменяет текст:
public class HtmlFilter : Stream
{
// Второстепенный код пропущен.
// Основной метод, производящий замену текста перед записью в поток.
public override void Write(byte[] buffer, int offset, int count)
{
Encoding encoding = HttpContext.Current.Response.ContentEncoding;
string s = encoding.GetString(buffer);
s = Regex.Replace(s, pattern, replacement);
byte[] outData = encoding.GetBytes(s);
_baseStream.Write(outData, 0, outData.Length);
}
}
Чем примечателен этот код? Тем, что он неправильный. Контент разбивается на порции, и эти порции записываются в поток по отдельности — метод Write() вызывается несколько раз. Это значит, что иногда в отфильтрованном контенте будут присутствовать незаменённые экземпляры искомого текста, которым "посчастливилось" попасть на границы порций, а значит Regex просто не найдёт и не заменит их. Самое плохое в этой ошибке то, что она выглядит как случайная, её очень сложно воспроизвести. Вероятность её проявления прямо пропорционально величине заменяемого текста (pattern'а). Чем он больше, тем вероятней то, что он окажется на границе порций контента. В моём случае заменяемый текст являлся частью URL, и мне даже удалось увидеть один "неправильный" URL.
Окей, как же тогда правильно заменять текст в контенте? Основной принцип — склеивать порции, потом анализировать их вместе, и после этого писать в поток и отсылать. На эту тему есть замечательный пост Рика Страла (Rick Strahl). Он реализовал удобный класс-фильтр, который решает эту проблему.
Вторая ловушка существует при фильтрации статического контента. Если включено сжатие статических файлов, IIS помещает сжатые статические оригинальные файлы в свой кэш. При последующих запросах IIS сразу отдаст файл из кэша, минуя потоковый фильтр. Выглядит это так: при первом запросе к статическому файлу возвращается содержимое файла с произведённой обработкой. При дальнейших запросах возвращается уже оригинальное содержимое, потому что взято оно из кэша. Побороть это можно отключением сжатия статического контента.
вторник, 25 сентября 2012 г.
Сравнение: const vs readonly
| Аспект | const | readonly |
| Место инициализации | Только при объявлении поля. | При объявлении поля, в конструкторах экземпляра, в статическом конструкторе. |
| Время инициализация | При компиляции. | При создании экземпляра класса или при обращении к статическим членам класса. |
| Поддерживаемые типы | Boolean, Char, Byte, SByte, Intl6, UIntl6, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, String и enum. Использовать ссылочные типы как константы не имеет смысла, т. к. единственное допустимое начальное значение таких констант — null. Исключение — тип String. | Любой тип. |
| Способ хранения | Хранится в метаданных сборки. Везде, где встречается константа, компилятор вставляет вместо неё само значение. В период выполнения память для неё не выделяется. | Хранится как обычное (instance) поле с выделением памяти в период выполнения. |
| Разделение между сборками | Везде, где встречается константа, определённая в другой сборке, компилятор вставляет вместо неё само значение из сборки. После компиляции, сборка с константой более не требуется для выполнения приложения (при условии, что используется только константа). Если константа будет изменена, то для использования нового значения в других сборках потребуется их перекомпиляция. | Разделяется как обычное поле. Сборка с reaonly полем должна присутствовать в списке ссылок у сборок-клиентов. |
Источники
- http://msdn.microsoft.com/ru-ru/library/acdd6hb7.aspx.
- Дж. Рихтер. CLR via C#. Программирование на платформе Microsoft .NET Framework 4.0 на языке C#. – С. 191.
среда, 19 сентября 2012 г.
Сравнение: abstract class vs interface
Представляю вольный и дополненный перевод таблицы из статьи на CodeProject.
Таблица различий между абстрактным классом и интерфейсом в C#
| Аспект | abstract class | interface |
| Назначение | Как любой базовый класс, представляет ядро поведения для всех наследников. Если в абстрактном классе не реализован ни один метод, имеет смысл превратить его в интерфейс. | Контракт, ничего более. Интерфейсы часто используются (и во основном предназначены для этого) как примеси без реализации при проектировании иерархии классов. |
| Реализация по умолчанию | Может быть частично или полностью реализован, предоставлять базовую функциональность. | Не может содержать какой-либо код. |
| Модификаторы доступа членов | Члены могут иметь все допустимые модификаторы доступа. | Только public. |
| Наследование | Наследование от абстрактного класса реализует отношение "является". | Наследование от интерфейса определяет отношение "реализует". |
| Множественное наследование | Класс может наследовать только один класс. | Класс может наследовать несколько интерфейсов. При этом он может и не реализовывать методы интерфейса, т. е. быть абстрактным. Сам интерфейс тоже может наследовать несколько интерфейсов. |
| Скорость | Быстро. | Требуется больше времения для поиска реализованного метода в соответствующем классе. |
| Расширение | При добавлении нового метода в абстрактный класс, мы можешь реализовать его, тем самым не нарушив работу наследующих классов. Если тело метода оставить нереализованным, потребуется его реализация в классах-наследниках с последующей перекомпиляцией. | При добавлении нового метода в интерфейс мы должны определить его во всех классах, реализующих интерфейс, с перекомпиляцией. |
| Члены | Может содержать все допустимые члены. | Не может содержать константы, поля, операторы, конструкторы экземпляров, деструкторы или типы. Допускаются: методы, свойства, события, индексаторы (свойства с параметрами). |
| Статические члены | Может содержать статические поля и методы. | Не может содержать статические поля и методы. |
Источники
- http://www.codeproject.com/Articles/11155/Abstract-Class-versus-Interface
- http://msdn.microsoft.com/ru-ru/library/ms173156.aspx
- Э. Гамма, Р. Хелм, Р. Джонсон, Д. Влиссидес. Приемы ООП. Паттерны проектирования.
- Дж. Рихтер. CLR via C#. Программирование на платформе Microsoft .NET Framework 4.0 на языке C#. — С. 322.
- Дж. Либерти. Программирование на C#.
суббота, 1 сентября 2012 г.
Проблемы при установке Async CTP v3
Я решил попробовать новое средство асинхронного программирования от Microsoft — Visual Studio Asynchronous Programming. Это расширение идёт вместе с C# 5 в составе Visual Studio 2012, а для Visual Studio 2010 есть пакет под названием Async CTP v3.
Скачал дистрибутив и запустил установку. Установка прошла без каких-либо видимых проблем. Однако, я не обнаружил каталога Microsoft Visual Studio Async CTP в My Documents. Погуглив, обнаружил, что это расширение конфиликтует с Silverlight 5 SDK и некоторыми обновлениями. Итак, если вы хотите корректно установить Async CTP v3 необходимо сделать следующее:
- Удалить предыдущую верию Async CTP (v1 или v2). Если у вас "недоустановленная" версия v3, то её тоже необходимо удалить.
- Удалить Silverlight 5 SDK.
- Установить все обновления в Центре обновления Windows. Ещё рекомендуют также установить и необязательные обновления, но тут без фанатизма.
-
В установленных обновлениях найти и удалить следующие:
- KB2549864
- KB2615527
- KB2635973
- KB2645410
- Запустить и установить Async CTP v3.
Первый признак того, что установка прошла корректно — информационное окно, появляющееся при завершении установки:
Ещё нужно проверить версии всех четырёх файлов:
- C:\Windows\Microsoft.Net\Framework\v4.0.30319\csc.exe
- C:\Windows\Microsoft.Net\Framework\v4.0.30319\vbc.exe
- C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\msvbide.dll
- My Documents\Microsoft Visual Studio Async CTP\Samples\AsyncCtpLibrary_Phone.dll
Правильные версии этих файлов:
| Async CTP v3 | |
| csc.exe | 4.0.30319.517 |
| vbc.exe | 10.0.30319.517 |
| msvbide.dll | 4.0.40219.355 |
| AsyncCtpLibrary_Phone.dll | 1.1.0.0 |
Как узнать версию файла: щелчок правой кнопкой по файлу -> Свойства -> Подробно.

