seoul
seoul

Reputation: 864

Delegate error in C#

My code is as follows:

class PropertyRetrievalClass
{
    public delegate object getProperty(string input);

    public object get_Chart_1(string iput)
    {
        Console.WriteLine(iput);
        return "";
    }
    public object get_Chart_2(string iput)
    {
        Console.WriteLine(iput);
        return "";
    }

    public PropertyRetrievalClass() { }
}

public static void Main()
        {
            int i = 1;
            PropertyRetrievalClass obj = new PropertyRetrievalClass();

            Delegate del = Delegate.CreateDelegate(typeof(PropertyRetrievalClass), obj, "get_chart_" + i.ToString());
            string output=  del("asldkl");
        }

It is giving me an error saying "error CS0118: 'del' is a 'variable' but is used like a 'method'"

What should I do to use this delegate? I want to call any of "get_chart_1" or "get_chart_2" function and both of them take a string input?

Thanks in advance...

Upvotes: 4

Views: 4125

Answers (5)

Fredrik Mörk
Fredrik Mörk

Reputation: 158309

You have two issues in your code.

  • A Delegate object is not a method, so you need to use a method on the Delegate object to invoke the method it refers
  • The first argument to CreateDelegate should be the delegate type, not the class containing a method you want to invoke.

Full working example:

public delegate void ParamLess();
class SomeClass
{
    public void PrintStuff()
    {
        Console.WriteLine("stuff");
    }
}
internal class Program
{
    private static Dictionary<int, int> dict = null;
    static void Main()
    {
        var obj = new SomeClass();
        Delegate del = Delegate.CreateDelegate(typeof(ParamLess), obj, 
                "PrintStuff", false);
        del.DynamicInvoke(); // invokes SomeClass.PrintStuff, which prints "stuff"
    }
}

In your case, the Main method should look like this:

public static void Main()
{
    int i = 1;
    PropertyRetrievalClass obj = new PropertyRetrievalClass();

    Delegate del = Delegate.CreateDelegate(
        typeof(PropertyRetrievalClass.getProperty), 
        obj, 
        "get_Chart_" + i.ToString());
    string output =  (string)del.DynamicInvoke("asldkl");
}

Update
Note that CreateDelegate is case sensitive on the method name, unless you tell it not to.

// this call will fail, get_chart should be get_Chart
Delegate del = Delegate.CreateDelegate(
        typeof(PropertyRetrievalClass.getProperty), 
        obj, 
        "get_chart_" + i.ToString());


// this call will succeed
Delegate del = Delegate.CreateDelegate(
        typeof(PropertyRetrievalClass.getProperty), 
        obj, 
        "get_Chart_" + i.ToString());


// this call will succeed, since we tell CreateDelegate to ignore case
Delegate del = Delegate.CreateDelegate(
        typeof(PropertyRetrievalClass.getProperty), 
        obj, 
        "get_chart_" + i.ToString(),
        true);

Upvotes: 3

Jamie Treworgy
Jamie Treworgy

Reputation: 24334

The other answers have addressed the problem with your code, but I wanted to offer an alternative.

If there are a limited, finite number of methods that your retrieval class is choosing from, and they have the same signatures, this can be done much more efficiently without using reflection:

public int MethodIndex {get;set;}
public static void Main()
{
    PropertyRetrievalClass obj = new PropertyRetrievalClass();
    Func<string,object> getChartMethod;
    switch(MethodIndex) 
    {
        case 1:
            getChartMethod = obj.get_chart_1;
            break;
        case 2:
            getChartMethod = obj.get_chart_2;
            break;
    }            
    string output=  getChartMethod("asldkl");
}

If there were a lot, you could just create an array instead of using a switch. Obviously you could just run the appropriate function directly from the switch, but I assume that the idea is you may want to pass the delegate back to the caller, and a construct like this lets you do that without using reflection, e.g.

public static Func<string,object> GetMethod
{
 ... just return getChartMethod directly
}

Upvotes: 1

R. Martinho Fernandes
R. Martinho Fernandes

Reputation: 234434

You can only call delegates with method call syntax, if they have a known signature. You need to cast your delegate to the delegate type you defined earlier.

var del = (PropertyRetrievalClass.getProperty)Delegate.CreateDelegate(typeof(PropertyRetrievalClass.getProperty), obj, "get_Chart_" + i.ToString());

You also need to change the first argument to CreateDelegate, because it should be the delegate type. And capitalize the "C" in "get_Chart_".

And then, you will need to cast the returned object to string:

string output= (string) del("asldkl");

Or change the delegate type and the methods to have string as their return type.

Upvotes: 0

Aliostad
Aliostad

Reputation: 81660

You cannot call a method on Delegate type. You have to use DynamicInvoke() which is very slowwwwwww.

Try this:

string output = (string) del.DynamicInvoke(new object[]{"asldkl"});

Upvotes: 0

Daniel A. White
Daniel A. White

Reputation: 190945

You are using the Delegate class not the delegate keyword.

Upvotes: 0

Related Questions