Прямо сейчас (в Swift 2.3), если вы используете:
myString.characters.count
метод вернет тип «Distance», если вам нужен метод для возврата Integer, вы должны напечатать приведение следующим образом:
var count = myString.characters.count as Int
Вам не нужно использовать эту расширенную версию реализации IDisposable, если ваш класс не использует напрямую неуправляемые ресурсы.
Простого
public virtual void Dispose()
{
_Writer.Dispose();
}
будет достаточно.
Если вашему потребителю не удается удалить ваш объект, он будет GC, как правило, без вызова Dispose, объект, удерживаемый _Writer, также будет GC, и у него будет финализатор, поэтому он все равно сможет очистить его неуправляемый ресурсы правильно.
Править
Проведя некоторое исследование ссылок, предоставленных Мэттом и другими, я пришел к выводу, что мой ответ здесь стоит . Вот почему: -
Предпосылка одноразовой реализации "шаблона" (под этим я подразумеваю защищенный виртуальный Dispose (bool), SuppressFinalize и т. Д. Marlarky) наследуемого класса состоит в том, что подкласс может держатся за неуправляемый ресурс.
Однако в реальном мире подавляющее большинство из нас, разработчиков .NET, даже близко не подходят к неуправляемым ресурсам. Если бы вам нужно было количественно оценить " было бы разумно. Следовательно, в значительно большем объеме «нормального» кода нам не нужно беспокоиться о всей этой ерунде. Если нам нужен IDisposable, мы можем использовать простой шаблон выше, наследуемый или нет.
Уф, рад снять это с моей груди. ;)
Вам не нужен метод Finalize
(деструктор), поскольку у вас нет неуправляемых объектов. Однако вы должны оставить вызов GC.SuppressFinalize
на тот случай, если класс, наследующий от Foo, имеет неуправляемые объекты и, следовательно, финализатор.
Если вы сделаете класс запечатанным, то вы знаете, что неуправляемые объекты являются никогда не будет входить в уравнение, поэтому нет необходимости добавлять перегрузку защищенного виртуального удаления (bool)
или GC.SuppressFinalize
.
Изменить:
@ AnthonyWJones возражает против этого: если вы знаете, что подклассы не будут ссылаться на неуправляемые объекты, все Dispose (bool)
и GC.SuppressFinalize
не нужны. Но в этом случае вам действительно нужно сделать классы внутренними
, а не общедоступными
, а метод Dispose ()
должен быть виртуальным
. Если вы знаете, что делаете, то не стесняйтесь следовать предложенному Microsoft шаблону, но вы должны знать и понимать правила, прежде чем нарушать их!
Вы должны проверить, что _Writer
не null
, прежде чем пытаться его удалить. (Это не Кажется вероятным, что он когда-нибудь будет null
, но на всякий случай!)
protected virtual void Dispose(bool disposing)
{
if (!_Disposed)
{
if (disposing && (_Writer != null))
{
_Writer.Dispose();
}
_Writer = null;
_Disposed = true;
}
}
Рекомендуется использовать финализатор только тогда, когда у вас есть неуправляемые ресурсы (например, собственные дескрипторы файлов, указатели памяти и т. Д.).
У меня есть два небольших предложения,
Это не обязательно иметь
Переменная " m_Disposed
" для проверки
вы ранее вызывали Dispose
на ваших управляемых ресурсах. Ты мог бы
используйте аналогичный код, например,
protected virtual void Dispose (bool dispose) { if (удаление) { если (_Writer! = ноль) _Writer.Dispose (); } _Writer = null; }
Открывайте файлы столько, сколько необходимо. Итак, в вашем примере вы должны проверить наличие файла в конструкторе, используя File.Exists
, а затем, когда вам нужно прочитать / записать файл, , затем вы откроете его и используйте его.
Кроме того, если вы просто хотите записать текст в файл, посмотрите File.WriteAllText
или File.OpenText
или даже File. AppendText
, предназначенный для текстовых файлов с ASCIIEncoding
.
В остальном, да, вы правильно реализуете шаблон .NET Dispose
.
Если вы откроете StreamWriter, вам также придется его удалить, иначе возникнет утечка.
У меня много таких классов - и я рекомендую сделать класс запечатан по возможности. IDisposable
+ наследование может работать, но в 99% случаев оно вам не нужно - и с ним легко ошибиться.
Если вы не пишете общедоступный API (в этом случае это приятно чтобы люди могли реализовать ваш код, как они того пожелают, то есть использовать IDisposable
), вам не нужно поддерживать его.
просто выполните:
public sealed class Foo : IDisposable
{
private StreamWriter _Writer;
public Foo(string path)
{
FileStream fileWrite = File.Open (path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
try {
_Writer = new StreamWriter (fileWrite, new ASCIIEncoding());
} catch {
fileWrite.Dispose();
throw;
}
}
public void Dispose()
{
_Writer.Dispose();
}
}
Обратите внимание на try ... catch; технически конструктор StreamWriter
может вызвать исключение,
Википедия: Финализаторы C ++ / CLI и автоматические переменные .
Например, реализация «безопасного» одноразового контейнера в C ++ / CLI выглядит так ...
public ref class MyDisposableContainer
{
auto_handle<IDisposable> kidObj;
auto_handle<IDisposable> kidObj2;
public:
MyDisposableContainer(IDisposable^ a,IDisposable^ b)
: kidObj(a), kidObj2(b)
{
Console::WriteLine("look ma, no destructor!");
}
};
Этот код правильно удалит kidObj и kidObj2 даже без добавления пользовательской реализации IDisposable, и она устойчива к исключениям в любой реализации Dispose (не то, чтобы они должны были возникать, но все же), и проста в обслуживании перед лицом большего количества членов IDisposable
или собственных ресурсов.
Не то, чтобы я был большим поклонником C ++ / CLI, но для кода, сильно ориентированного на ресурсы, он легко превзошел C #, и он имеет абсолютно блестящее взаимодействие как с управляемым, так и с собственным кодом - короче говоря, идеальный связующий код ;-) . Я стараюсь писать 90% своего кода на C #, но использую C ++ / CLI для всех нужд взаимодействия (особенно.
" Комментарии к документации XML (Руководство по программированию на C #) обычно не предполагается, что он играет с управляемыми объектами, когда их удаляет финализатор (который вам в любом случае не нужен, как указывали другие).