2

I'm just beginning understanding delegates, I have a class that implemens IDisposable:

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

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

  public void Dispose()
  {
    // Cleanup
  }
}

A method (defined in an another class) that is using 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
      }
    }
}

The actual question: how pass the Zero() function to UseMyClass method? Do I have to create an instance of MyClass (I would like to avoid this...)?

public static void main(string[] args)
{
  // Call AnotherClass method, by passing Zero()
  // or One() but without instatiate MyCLass
  AnotherClass.UseMyClass(??????????);
}
gremo
  • 47,186
  • 75
  • 257
  • 421
  • 1
    Maybe if you can explain what you are trying to do, we might be able to recommend something better. – IAbstract Dec 05 '10 at 05:14
  • MyClass is DAL, I have some member methods to call. From another class (business) is using the DAL and define "UseMyClass" method. How can I pass Zero() function to the business class from the GUI, without create a new instance of MyClass? – gremo Dec 05 '10 at 05:28
  • You might consider using an interface on your MyClass object to expose the Zero() property and then have your UseMyClass function take that interface as an argument. IMHO, seems like a better way to me. –  Dec 05 '10 at 05:31
  • No, i won't. I don't like explosion of hierarchy... see my edits – gremo Dec 05 '10 at 05:33
  • I'm confused here. If the function `Zero()` is not `static`, how do you expect to call it - either as a delegate or any other way - without an instance of `MyClass`? And if you want to call it without an instance of `MyClass`, why don't you just make it `static`? – Carson63000 Dec 05 '10 at 05:44
  • Have a look at this: http://stackoverflow.com/questions/4083028/build-a-static-delegate-from-non-static-method You can do it using Delegate.CreateDelegate but this method would require reflection. –  Dec 05 '10 at 05:50
  • MyClass can't be static because implements IDisposable, Zero() can't be static because it needs instance members. – gremo Dec 05 '10 at 05:54
  • Gremo: What you want is a method that is not bound to an instance. This is called an "open delegate". Ben's answer (http://stackoverflow.com/questions/4357480/how-pass-delegate-to-a-method-where-delegates-are-non-static/4357622#4357622) is correct. – Gabe Dec 05 '10 at 06:57

3 Answers3

2

Is your intent that the instance is provided by the caller of the delegate, and not the creator of the delegate? C# does support such an unbound delegate, it's called an open delegate, and the instance becomes a parameter.

You have to use Delegate.CreateDelegate to create an open delegate, something like this:

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")
    )
);

Of course, you can do it much more easily with a shim:

AnotherClass.UseMyClass( mc => mc.One() ); // C# 3 or later
AnotherClass.UseMyClass( delegate(MyClass mc) { return mc.One(); } ); // C# 2
Gabe
  • 84,912
  • 12
  • 139
  • 238
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
1

Because it's an instance method, if you want to call it, you need an instance. That's simply how the CLR works. However, there are two options you could go with:

  • Make the member functions static. If they're as simple as returning a static value, there's no reason for them to be instance methods. However, if you do actually require instance data...
  • Use a singleton instance. This way you don't need to create a new instance every time you want to call your static method.

You can do the latter like this:

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
}

Then, you can call your static method like so:

AnotherClass.UseMyClass(MyClass.SingletonInstance.Zero);
Adam Maras
  • 26,269
  • 6
  • 65
  • 91
0

Cant be done without instantiation. Heres how you can do it:


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

basarat
  • 261,912
  • 58
  • 460
  • 511