2010-12-05 70 views
2

Je commence à peine à comprendre les délégués, j'ai une classe qui implemens IDisposable:Comment passer un délégué à une méthode, où les délégués sont non statiques?

public class MyClass : IDisposable 
{ 
    public delegate int DoSomething(); 

    public int Zero() {return 0;} 
    public int One() {return 1;} 

    public void Dispose() 
    { 
    // Cleanup 
    } 
} 

Méthode (définie dans une autre classe) qui utilise MyClass:

public class AnotherCLass 
{ 
    public static void UseMyClass(MyClass.DoSomething func) 
    { 
     using (var mc = new MyClass()) 
     { 
     // Call the delegate function 
     mc.func(); // <-------- this is what i should actually call 
     } 
    } 
} 

La réelle question : comment passer la fonction Zero() à la méthode UseMyClass? Dois-je créer une instance de MyClass (je voudrais éviter cela ...)?

public static void main(string[] args) 
{ 
    // Call AnotherClass method, by passing Zero() 
    // or One() but without instatiate MyCLass 
    AnotherClass.UseMyClass(??????????); 
} 
+1

Peut-être que si vous le pouvez expliquer ce que vous essayez de faire, nous pourrions être en mesure de recommander quelque chose de mieux. – IAbstract

+0

MyClass est DAL, j'ai quelques méthodes membres à appeler. D'une autre classe (entreprise) utilise le DAL et définit la méthode "UseMyClass". Comment puis-je passer la fonction Zero() à la classe business à partir de l'interface graphique, sans créer une nouvelle instance de MyClass? – gremo

+0

Vous pouvez envisager d'utiliser une interface sur votre objet MyClass pour exposer la propriété Zero() et demander à votre fonction UseMyClass de prendre cette interface en tant qu'argument. À mon humble avis, semble être un meilleur moyen pour moi. –

Répondre

1

Parce qu'il est une méthode d'instance, si vous voulez l'appeler, vous avez besoin d'une instance. C'est tout simplement comme ça que fonctionne le CLR. Cependant, il existe deux options possibles:

  • Rendre les fonctions membres statiques. Si elles sont aussi simples que renvoyer une valeur statique, il n'y a aucune raison pour qu'elles soient des méthodes d'instance. Toutefois, si vous avez réellement besoin de données d'instance ...
  • Utilisez une instance singleton. De cette façon, vous n'avez pas besoin de créer une nouvelle instance chaque fois que vous voulez appeler votre méthode statique.

Vous pouvez faire ce dernier comme ceci:

public class MyClass 
{ 
    private static MyClass singletonInstance; 
    public static MyClass SingletonInstance 
    { 
     get 
     { 
      if (singletonInstance == null) 
      { 
       singletonInstance = new MyClass(); 
      } 
      return singletonInstance; 
     } 
    } 

    // the rest of your class implementation 
} 

Ensuite, vous pouvez appeler votre méthode statique comme ceci:

AnotherClass.UseMyClass(MyClass.SingletonInstance.Zero); 
0

ne peux pas être fait sans instanciation. Voici comment vous pouvez le faire:

 

public static void main(string[] args) 
{ 
    // Call AnotherClass method, by passing Zero() 
    // or One() but without instatiate MyCLass 
    AnotherClass.UseMyClass((new MyClass()).Zero); 
} 
 
+0

J'avais peur que ce soit la seule solution ... merci btw – gremo

+0

les bienvenus. J'espère que vous apprécierez C# autant que moi :) – basarat

2

Est-ce votre intention que l'instance est fournie par l'appelant du délégué, et non le créateur du délégué? C# prend en charge un tel délégué non lié, il est appelé délégué ouvert, et l'instance devient un paramètre.

Vous devez utiliser Delegate.CreateDelegate pour créer un délégué ouvert, quelque chose comme ceci:

public class MyClass : IDisposable 
{ 
    public delegate int DoSomething(); 

    public int Zero() {return 0;} 
    public int One() {return 1;} 

    public void Dispose() 
    { 
    // Cleanup 
    } 
} 

public class AnotherCLass 
{ 
    public static void UseMyClass(Converter<MyClass,int> func) 
    { 
     using (var mc = new MyClass()) 
     { 
     // Call the delegate function 
     func(mc); 
     } 
    } 
} 

AnotherClass.UseMyClass(
    (Converter<MyClass, int>)Delegate.CreateDelegate(
     typeof(Converter<MyClass, int>), 
     typeof(MyClass).GetMethod("One") 
    ) 
); 

Bien sûr, vous pouvez le faire beaucoup plus facilement avec une cale:

AnotherClass.UseMyClass(mc => mc.One()); // C# 3 or later 
AnotherClass.UseMyClass(delegate(MyClass mc) { return mc.One(); }); // C# 2 
+0

Non, devrait être mc.func(), pas comme vous l'avez écrit. – gremo

+0

Gremo: C# ne supporte pas faire 'mc.func()' comme vous voulez. La syntaxe 'func (mc)' est correcte. – Gabe