Dima
Dima

Reputation: 51

Delegate - Method Name Expected Error

I'm writing a console calculator on c#. I need the following code start working:

Dictionary<string, Delegate> functions = new Dictionary<string, Delegate>();

private void AddMyFunction (Delegate d, string name)
{
    if (name == null)
    {
        name = d.Method.Name;
    }
    functions.Add (name, d);
}

public void AddFunction (Func<decimal, decimal> f, string name)
{
    AddMyFunction (f, name);
}

public void AddFunction (Func<decimal, decimal, decimal> f, string name)
{
    AddMyFunction (f, name);
}        

public double PerformOperation (string op, decimal x)
{
    return functions [ op ] (x);
}    

In the function "PerformOperation" the error: "Method name expected" comes out. Please help someone.

Upvotes: 3

Views: 2374

Answers (2)

p.s.w.g
p.s.w.g

Reputation: 149068

Change it to this:

public decimal PerformOperation (string op, decimal x)
{
    return (decimal)(functions[op].DynamicInvoke(x));
}  

And it will work. However, I'd recommend something a little more strongly typed. Perhaps keep multiple dictionaries, one for each delegate type, like this:

Dictionary<string, Func<decimal, decimal>> func1;
Dictionary<string, Func<decimal, decimal, decimal>> func2;

public void AddFunction (Func<decimal, decimal> f, string name)
{
    func1.Add(name, f);
}

public void AddFunction (Func<decimal, decimal, decimal> f, string name)
{
    func2.Add(name, f);
} 

public decimal PerformOperation (string op, decimal x)
{
    return func1[op](x);
}

public decimal PerformOperation (string op, decimal x, decimal y)
{
    return func2[op](x, y);
}

Upvotes: 4

Jon Skeet
Jon Skeet

Reputation: 1503519

The problem is that you're trying to use the bare Delegate type as if it were a specific delegate type. If you change your dictionary to:

Dictionary<string, Func<decimal, double>>

then that error goes away - but you won't be able to add a Func<decimal, decimal> as a value in the dictionary, of course... or a Func<decimal, decimal, decimal>.

You could use Delegate.DynamicInvoke if you don't want to tie yourself to a specific delegate type - but then you'd still have a problem of handling the fact that you're expecting a double return value but calling a delegate which returns a decimal. You'll get an unboxing error if you just cast the result of DynamicInvoke to double.

There's also the problem that the delegate you're trying to call may have two parameters and you're only supplying one argument.

Basically you need to be more consistent about what you want the values in the dictionary to be.

Upvotes: 5

Related Questions