2008-10-21 7 views
1

Je souhaite que nous avons tendance « utilisable » en C#, lorsque le bloc de code d'utilisation construction serait passé à une fonction en tant que délégué:IUsable: le contrôle des ressources d'une meilleure façon que IDisposable

class Usable : IUsable 
{ 
    public void Use(Action action) // implements IUsable 
    { 
    // acquire resources 
    action(); 
    // release resources 
    } 
} 

et dans le code utilisateur :

using (new Usable()) 
{ 
    // this code block is converted to delegate and passed to Use method above 
} 

Plus:

  • exécution contrôlée, les exceptions
  • Le fait d'utiliser « utilisable » est visible dans la pile d'appel

Moins:

  • Coût du délégué

Pensez-vous qu'il est possible et utile, et si elle doesn pas de problèmes du point de vue linguistique? Y a-t-il des pièges que vous pouvez voir?

EDIT: David Schmitt proposed les éléments suivants

using(new Usable(delegate() { 
    // actions here 
}) {} 

Il peut fonctionner dans le scénario de l'échantillon comme ça, mais en général vous avez des ressources déjà allouées et que vous voulez qu'il ressemble à ceci:

using (Repository.GlobalResource) 
{ 
    // actions here 
} 

Où GlobalResource (oui, je sais que les ressources globales sont mauvaises) implémente IUsable. Vous pouvez réécrire est aussi courte que

Repository.GlobalResource.Use(() => 
{ 
    // actions here 
}); 

Mais il semble un peu bizarre (et plus bizarre si vous implémentez l'interface explicitement), et cela est si souvent le cas dans diverses saveurs, que je pensais qu'il mérite d'être nouveau sucre syntaxique dans une langue.

Répondre

1

Vous pouvez déjà avoir plus de cela en utilisant un délégué anonyme comme celui-ci:

using(new Usable(delegate() { 
    // actions here 
}) {} 

Bien sûr, enroulant que dans quelque fonction, ou la mise en œuvre directement l'essai/pourrait finalement rendre ce non seulement utile, mais même un peu joli.

3

à mon humble avis, je ne vois pas une grande utilité pour ce modèle parce que:

  1. en utilisant le bloc nécessite déjà l'objet d'avoir une interface IDisposable, afin que nous puissions utiliser l'interface IDisposable pour l'exécution contrôlée
  2. De Où passons-nous l'objet Action ici?

J'avais déjà utilisé ce type de modèle avec succès pour des actions de base de données en utilisant IDisposable.

2

Qu'en est-:

class Usable<T> where T : ICriticalResource, new() 
{ 
    static void Do(Action<T> action) { 
     ICriticalResource resource = new T(); 
     resource.Acquire(); 
     action(resource); 
     resource.Relese(); 
    } 
} 

Ensuite, vous l'utiliser pour tout ce qui met en œuvre ICritialResource.

Usable<SomeResource>.Do(resource => resource.SomeMethod()); 

Une autre option consiste à utiliser IDisposable comme il est. Oui, il pourrait ne pas être aussi élégant que possible, mais au moins la plupart des gens sont habitués.

Questions connexes