Arman Hamid Mosalla
Arman Hamid Mosalla

Reputation: 3355

How to pass two function to another function with a delegate for parameters in C#

I am struggling to understand delegates and for that I created a simple example for myself but it doesn't work the way I want it to, here is my example:

my functions:

class Functions
{

    public string MyFname(string MyString) 
    {

        return MyString;


    }
    public string MyLname(string MyString)
    {

        return MyString;


    }


}

delegate:

class DelClass
{
    public delegate string StrDelegate(string OutPutString);

    public void StringCon(StrDelegate Fname,StrDelegate Lname) 
    {

        Console.WriteLine(Fname + " " + Lname);

    }
}

Main:

class Program
{
    static void Main(string[] args)
    {
        DelClass MyDel = new DelClass();
        Functions MyTster = new Functions();
        DelClass.StrDelegate Name = new DelClass.StrDelegate(MyTster.MyFname);
        Name("SomeVariableName");
        DelClass.StrDelegate Family = new DelClass.StrDelegate(MyTster.MyLname);
        Family("SomeVariableFamilyName");
        MyDel.StringCon(Name, Family);

    }
}

The problem is Console window doesn't show my passed string instead it shows the undermentioned text:

MyDelegateMethodInMethod.DelClass+StrDelegate MyDelegateMethodInMethod.DelClass+ StrDelegate

And when I try to invoke the passed function in StringCon body like this:

Console.WriteLine(Fname() + " " + Lname();

The compiler complain that "Delegate 'StrDelegate' does not take 0 arguments" but I don't want to pass an argument in StringCon's passed parameters, I want to do it in my Main function, is this even possible with delegates?

Upvotes: 0

Views: 2082

Answers (3)

Icepickle
Icepickle

Reputation: 12796

This is not really how you should use delegates, delegates are mainly used as callback functions, or for EventHandlers, or when you like invoke a function.

an example of an EventHandler could be

public delegate void ReportErrorDelegate(object sender, MyCustomEventArgs e);

with a class

public class MyCustomEventArgs : EventArgs
{
     // some implementation
     public MyCustomEventArgs() 
     {
     }

     public MyCustomEventArgs(object argument)
         : this()
     {
         ....
     }
}

and afterwards you could create an event which is based on your delegate as

public interface IRaiseMyCustomEventArgs
{
     event ReportErrorDelegate CustomEventFired;
}

which you could then implement as

public class RaiseMyCustomEventArgs : IRaiseMyCustomEventArgs
{
     public event ReportErrorDelegate CustomEventFired;

     protected virtual void RaiseCustomEventArgs(object argument)
     {
         var local = CustomEventFired;
         if (local != null) {
             local.Invoke(this, new MyCustomEventArgs(argument));
         }
     }
}

an other option could be to recall a method after you detect that a UI interaction needs to be Invoked, like such

public delegate void SetTextDelegate(TextBox tb, string text);

public void SetText(TextBox tb, string text)
{
     if (tb.InvokeRequired) 
     {
          tb.Invoke(new SetTextDelegate(SetText), tb, text);
          return;
     }
     tb.Text = text;
}

that would be called from a thread running inside a windows application (eg)

public void RunThread() 
{
     // assuming TextBox1 exists on the form
     Thread t = new Thread(() => {
         SetText(TextBox1, "Hello World");
     });
     t.Start();
}

Upvotes: 2

ShayD
ShayD

Reputation: 930

If you do not want to pass a string as input, you should declare the delegates appropriately:

class DelClass
{
    public delegate string StrDelegate();
    public void StringCon(StrDelegate Fname,StrDelegate Lname) 
    {
        Console.WriteLine(Fname() + " " + Lname());
    }
}

From what you wrote, you want to save the string property somewhere - but the delegate is not the place to do it.You can create an object with FName, LName properties:

class Functions
{
    public string MyFname() { return MyFnameProperty; }
    public string MyLname() { return MyLnameProperty; }
    public string MyFnameProperty { get; set; }
    public string MyLnameProperty { get; set; }
}

And finally, in Main you will write:

class Program
{
    static void Main(string[] args)
    {
        DelClass MyDel = new DelClass();
        Functions MyTster = new Functions();
        DelClass.StrDelegate Name = new DelClass.StrDelegate(MyTster.MyFname);
        MyTster.MyFnameProperty ="SomeVariableName";
        DelClass.StrDelegate Family = new DelClass.StrDelegate(MyTster.MyLname);
        MyTster.MyLnameProperty = "SomeVariableFamilyName";
        MyDel.StringCon(Name, Family);
    }
}

Upvotes: 2

jmcilhinney
jmcilhinney

Reputation: 54417

A delegate is an object that contains a reference to a method. Invoking the delegate has the effect of executing the method. Your two methods each have a String parameter so to execute either of those methods you pass pass a single String argument. That means that, when you invoke your delegates, they need to pass a single String argument to the method they execute. Where do you think that value is going to come from? The delegate is not going to pluck it out of thin air. You have to pass it to the delegate when you invoke it. In this code:

public void StringCon(StrDelegate Fname,StrDelegate Lname) 
{
    Console.WriteLine(Fname + " " + Lname);
}

where are you doing that? You're not. You have to provide the arguments to the delegates in order for them to provide them to the methods:

public void StringCon(StrDelegate Fname,StrDelegate Lname) 
{
    Console.WriteLine(Fname("John") + " " + Lname("Doe"));
}

This is a very poor demonstration though, because your methods don't really do anything useful. How about defining a method does something useful like this:

public string GetFullName(string givenName, string familyName)
{
    return givenName + " " + familyName;
}

and a corresponding delegate:

public delegate string FullNameGetter(string givenName, string familyName);

and then invoking it like so:

var fng = new FullNameGetter(GetFullName);

Console.WriteLine(fng("John", "Doe"));

Upvotes: 7

Related Questions