AnoopDV
AnoopDV

Reputation: 305

Use delegates to choose function at runtime

I am new to C# and still understanding the concept of delegates. What I know of delegates is that delegates define a function signature and functions with the same signature can be added to that delegate.

public class ss
{
    public delegate void sampleDelegate();

    public ss()
    {
        sampleDelegate s1 = new sampleDelegate(sampleMethod);
        s1+= new sampleDelegate(sampleMethod2);
        s1();
    }


    public static void sampleMethod()
    {

    }
    public static void sampleMethod2()
    {

    }
}

In the above code I create a delegate and give it sampleMethod and sampleMethod2. When I call s1() it calls both sampleMethod() and sampleMethod2().

What if I want to only call one of those methods and that decision is to be made at runtime?

I may be missing something very small but delegates are really confusing to understand.

Upvotes: 1

Views: 1496

Answers (2)

Matías Fidemraizer
Matías Fidemraizer

Reputation: 64943

Delegates are like pointers to a method. At run-time, there's nothing that differentiates calling a delegate or a method excluding that a method is a member of an object:

some.Method();
someDelegate();

The goal of delegates is creating a blackbox where you expect some code to put some behavior, and you simply rely on a method signature.

At the end of the day, they're like method interfaces:

// It must be a parameterless method which returns no value
public delegate void Action();

// vs

// It must be a class which implements a parameterless method "Do"
// which returns no value
public interface Action
{
    void Do();
}

That is, a method can't be conditionally be switched with other, but you need to use regular control flow blocks like if or switch to take decisions about what to do.

In order to don't duplicate Jon Skeet's answer, I'll add another possible solution:

    string text = "";

    sampleDelegate s1 = () =>
    {
         if(!string.IsNullOrEmpty(text)) 
         {
             SampleMethod1();
         }
         else
         {
             SampleMethod2();
         }
    };

    s1();

Check that, instead of creating two instances of sampleDelegate you can create one that handles the conditional logic to either call SampleMethod1 or SampleMethod2.

The whole () => { } thing is called anonymous delegate.

It can be also expressed as follows:

    string text = "";

    sampleDelegate s1 = delegate()
    {
         if(!string.IsNullOrEmpty(text)) 
         {
             SampleMethod1();
         }
         else
         {
             SampleMethod2();
         }
    };

But don't use above syntax... It comes from the old .NET days (.NET 1.0/1.1/2.0).

In summary, a delegate could or could not be provided as an actual class method, but you can combine class methods with anonymous delegates to meet your needs.

What if i want to only call one of those methods and that decision is to be made at runtime? I may be missing something very small but delegates are really confusing to understand.

Actually this is the reason to use delegates, but you're right when you say you're missing something.

Delegates are used to situations like the following one:

public void DoStuff(string text, Func<string, string> textFormatter = null)
{
    Console.WriteLine(textFormatter != null ? textFormatter(text) : text);
}

You might call DoStuff either this way DoStuff("hello world") or DoStuff("hello world", text => $"<strong>{text}</strong>").

DoStuff method implementation doesn't know how to format the given text, and you provide an optional parameter to give a delegate as argument that will receive the whole text to format and it will return the formatted text.

Isn't this some way conditional after all? Based on the caller, DoStuff formats the text in a custom way. You can even provide a default format:

public void DoStuff(string text, Func<string, string> textFormatter = null)
{
    // We'll give a default formatter if none is provided ;)
    if(textFormatter == null)
      textFormatter = text => $"<span>{text}</span>";

    Console.WriteLine(textFormatter(text));
}

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1503270

What if i want to only call one of those methods and that decision is to be made at runtime?

Then you don't combine them together, basically. For example:

// Names changed to be more conventional

SampleDelegate s1 = someCondition
    ? new SampleDelegate(SampleMethod)
    : new SampleDelegate(SampleMethod2);
// This will call either SampleMethod or SampleMethod2, depending on condition
s1(); 

Note that normally I'd use a method group conversion, but you can't use method groups for the second and third operands of the conditional operator. You could use:

SampleDelegate s1;
if (condition) {
    s1 = SampleMethod;
} else {
    s2 = SampleMethod2;
}

... or

SampleDelegate s1 = someCondition
    ? new SampleDelegate(SampleMethod)
    : SampleMethod2;

Neither of these looks particularly nice to me though.

Upvotes: 3

Related Questions