resource-cleanup usa a interface IDispose para sinalizar que os recursos de um objeto ou outro estado do programa precisavam de ser libertados ou repostos quando o objeto já não era necessário (e que confiar no coletor de lixo não o conseguiria fazer nem dar o nível de controlo necessário) e que o método IDisposable.Dispose() era o local natural para essas operações de limpeza.
Existe outra construção, o bloco using, que permite, do ponto de vista de quem chama, reunir toda a gestão do tempo de vida dos recursos numa única instrução.
using (var file = new File("my_secrets"))
{
file.WriteSecret("xxxxxxx");
}
No exemplo acima, os recursos do sistema de ficheiros associados a file são libertados de volta para o sistema operativo quando se sai do bloco using.
Para que o padrão funcione, a variável na instrução using tem de ser um tipo de referência que implemente a interface IDisposable e tem de libertar recursos/repor o estado do programa no seu método Dispose().
O C# 8 introduz um refinamento deste padrão. Uma instrução using pode ser colocada no início de um bloco.
using var drawingResource = some_provided_or_new_object;
try
{
drawingResource.DrawSomething();
}
catch (Exception)
{
throw;
}
Os programadores de Java podem reconhecer nisto um análogo do mecanismo de gestão automática de recursos introduzido no Java 7.
Voltaste a trabalhar no sistema ORM (mapeamento objeto-relacional) apresentado em object-relational-mapping.
A nossa análise de utilização do ORM mostra que 95% das transações são executadas dentro de um único método que as invoca, e decidiu-se que seria mais adequado ter um único método do ORM que abrisse, escrevesse e confirmasse uma transação.
A base de dados tem os seguintes métodos de instância:
Database.BeginTransaction() inicia uma transação na base de dados.Database.Write(string data) escreve dados na base de dados dentro da transação. Se receber dados inválidos, é lançada uma exceção. Uma tentativa de chamar este método sem que BeginTransaction() tenha sido chamado provoca o lançamento de uma exceção. Se for bem-sucedido, o estado interno da base de dados passa a DataWritten.Database.EndTransaction() confirma a transação na base de dados. Pode lançar uma exceção se não conseguir fechar a transação ou se Database.BeginTransaction() não tiver sido chamado.Database.Dispose() limpa a base de dados se for lançada uma exceção durante uma transação. Isto faz com que o estado da base de dados passe a Closed.Implementa o método Orm.Write() para iniciar uma transação na base de dados, escrever os dados recebidos e confirmar a transação. Todas as exceções, incluindo InvalidOperationException, devem poder chegar a quem chama o método, sem serem registadas nem sofrerem qualquer outra intervenção.
Database db = new Database();
Orm orm = new Orm(db);
orm.Write("good write");
// => database has an internal state of State.Closed
orm.Write("bad write");
// => an exception is thrown but database is left with an internal state of State.Closed
orm.Write("bad commit");
// => an exception is thrown but database is left with an internal state of State.Closed
Já passaram alguns meses desde que Orm.Write() foi introduzido e há divisão na equipa. Muitos programadores gostariam que o ORM tratasse os erros quando são lançadas exceções e devolvesse simplesmente a quem chama uma indicação de sucesso.
Implementa o método Orm.WriteSafely() para iniciar uma transação na base de dados, escrever os dados recebidos e confirmar a transação (como acima). Deve devolver true se a escrita tiver sido bem-sucedida e false caso contrário. Não tentes registar a exceção.
Database db = new Database();
Orm orm = new Orm(db);
orm.WriteSafely("good write");
// => true
orm.WriteSafely("bad write");
// => false
orm.WriteSafely("bad commit");
// => false
Inscreve-te no Exercism para aprenderes e dominares C# com 62 conceitos178 exercícios, e mentoria humana real, tudo grátis.