Mahmood Shahrokni
Mahmood Shahrokni

Reputation: 236

passing a method as a constructor's parameter

While I was looking at some c# code I found a new class declaration which had passed a method as a constructor’s parameter.This is my first time I have seen something like this and it has no meaning for me .Although the whole application works fine I am still interested to know what is the main idea behind the scene.

var c = new List<TheClass>
{
    new TheClass(TheMethod);
}

private void TheMethod()
{
    //do somthing
}

Upvotes: 2

Views: 18421

Answers (4)

Matthew Watson
Matthew Watson

Reputation: 109567

There are many reasons that you might want to pass a method into the constructor of a class.

One of the most important is for so-called Dependency Injection, where want to inject a dependency into a class.

Suppose that a class needs to create an object. Normally, that class would do something like var item = new MyConcreteClass();.

However, that creates a strong dependency between the class creating the object and MyConcreteClass. This can make it harder to unit test or change implementations.

To circumvent this problem, you can do this:

  1. Extract from MyConcreteClass an interface (say IMyInterface) which contains all the things you need to use from inside the class being written.
  2. Pass to the class constructor a Func method which creates and returns a concrete class as IMyInterface.
  3. Inside the class being written, call that Func to create the object rather than creating it directly using new.

The Func is therefore acting as a factory.

Code might look like this:

using System;

namespace Spacelabs.WcfDuplexDemo.Client
{
    static class Program
    {
        static void Main()
        {
            var myClass = new MyClass(() => new MyConcreteClass());

            myClass.DoSomething();
        }
    }

    public interface IMyInterface
    {
        string MyMethod(int param);
    }

    public sealed class MyConcreteClass : IMyInterface
    {
        public string MyMethod(int param)
        {
            return param.ToString();
        }
    }

    public sealed class MyClass
    {
        private readonly Func<IMyInterface> createMyInterface;

        public MyClass(Func<IMyInterface> createMyInterface)
        {
            this.createMyInterface = createMyInterface;
        }

        public void DoSomething()
        {
            // Instead of var item = new MyConcreteClass(), we do the following:

            var item = createMyInterface();
            Console.WriteLine(item.MyMethod(12345));
        }
    }

Upvotes: 1

user4063668
user4063668

Reputation:

Are you unclear of why a method is being passed as an argument or specificly as an argument in a constructor?

CodeCaster already spoke short about Action delegates and if you're interested in storing methods in delegates like Action, I suggest you read up on Delegates here

I'd like to provide a short example of a class that contains an Action delegate: RelayCommand -> I've illustrated the use of this delegate with the MVVM pattern below:

class ViewModelDefault : INotifyPropertyChanged
{
    public string TextProperty { get; set;}

    public ICommand ButtonProperty 
    { 
        get {
            RelayCommand relayCommand = new RelayCommand(ExecuteCommand); 
            return relayCommand; 
        } 
    }

    private void ExecuteCommand() 
    {
        HandlerClass handler = new HandlerClass();
        handler.SaveTextInTextfile(TextboxProperty);
    }

    ...
}

In the MVVM pattern, your main focus is to seperate data, logic and view, which is why using Delegate is perfect in this scenario.

You'd normally want to bind a property such as a string from the ViewModel to a View UI Element such as a TextBox.

Making use of delegates, allows you to bind a method (which would otherwise not be bindable to a UI element) through an Action property.

In the example above, the method ExecuteCommand is stored in an action field inside the RelayCommand object. This is bindable to a UI element, and will execute the method once it's requested.

Upvotes: 0

NeddySpaghetti
NeddySpaghetti

Reputation: 13495

The main idea is to defer execution of the method and control when it gets executed.

One use case for this is passing a method that creates and object so that the class controls when the object is created and it can control how many times it is created.

Upvotes: 0

CodeCaster
CodeCaster

Reputation: 151594

I guess the TheClass constructor accepts an Action delegate:

public class TheClass
{
    private readonly Action _action;
    public TheClass(Action action)
    {
        _action = action;
    }
}

This way TheClass can execute the provided action at a later time, and more than once.

For example:

public void DoAction()
{
    _action();
}

You could also do:

var theClass = new TheClass(() => TheMethod());

Upvotes: 11

Related Questions