gremo
gremo

Reputation: 48899

How pass delegate to a method, where delegates are non static?

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(??????????);
}

Upvotes: 2

Views: 4887

Answers (3)

Ben Voigt
Ben Voigt

Reputation: 283634

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

Upvotes: 2

basarat
basarat

Reputation: 275849

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

Upvotes: 0

Adam Maras
Adam Maras

Reputation: 26853

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

Upvotes: 1

Related Questions