Существует множество причин, по которым RAII не более известен. Во-первых, название не особо очевидное. Если бы я еще не знал, что такое RAII, я бы никогда не догадался об этом по названию. (Получение ресурсов - это инициализация? Какое отношение это имеет к деструктору или очистке, что на самом деле характеризует RAII?)
Во-вторых, он не работает так же хорошо на языках без детерминированной очистки.
В C ++ мы точно знаем, когда вызывается деструктор, мы знаем порядок, в котором вызываются деструкторы, и мы можем определить их, чтобы они делали все, что захотим.
В большинстве современных языков все собирается сборщиком мусора, что усложняет реализацию RAII. Нет причин, по которым нельзя было бы добавить RAII-расширения, скажем, в C #, но это не так очевидно, как в C ++. Но, как отмечали другие, Perl и другие языки поддерживают RAII, несмотря на сборку мусора.
Тем не менее, все еще можно создать свою собственную оболочку в стиле RAII на C # или других языках. Некоторое время назад я делал это на C #. Мне нужно было что-то написать, чтобы соединение с базой данных было закрыто сразу после использования, задача, которую любой программист на C ++ сочтет очевидным кандидатом на использование RAII. Конечно, мы могли бы обернуть все в using
-операторы всякий раз, когда использовали соединение с базой данных, но это просто беспорядочно и подвержено ошибкам.
Мое решение заключалось в том, чтобы написать вспомогательную функцию, которая принимала делегат в качестве аргумента, а затем при вызове открывала соединение с базой данных и внутри оператора using передавала его функции делегата, псевдокод:
T RAIIWrapper<T>(Func<DbConnection, T> f){
using (var db = new DbConnection()){
return f(db);
}
}
Все еще не такой красивый или очевидный, как C ++ - RAII, но он достиг примерно того же. Всякий раз, когда нам требуется DbConnection, мы должны вызывать эту вспомогательную функцию, которая гарантирует, что впоследствии она будет закрыта.
person
jalf
schedule
28.12.2008