54

I have created the following function:

public void DelegatedCall(Action<Object> delegatedMethod)

And defined the following method

public void foo1(String str) { }

However, when I try to call DelegateCall with foo1:

DelegatedCall(foo1);

...I get the following compiler error:

Argument 1: cannot convert from 'method group' to 'System.Action<object>'

What is the reason for this error and how can I correct it? Unfortunately, casting foo1 to Action is not an option.

DavidRR
  • 18,291
  • 25
  • 109
  • 191
Jonathan
  • 543
  • 1
  • 4
  • 5

2 Answers2

35

DelegatedCall expects a delegate that takes any object as an argument. But your function foo1 that you are passing to DelegatedCall can only cope with a string argument. So, the conversion isn't type-safe and thus is not possible.

Input parameters are contra-variant, but your code needs covariance. (See Difference between Covariance & Contra-variance.)

You can make DelegatedCall generic:

DelegatedCall<T>(Action<T> action)

...or have it take any delegate:

DelegatedCall(Delegate action)

But then implementing it is ugly and requires reflection. It also doesn't verify that the function has only one parameter at compile-time.

Community
  • 1
  • 1
CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
  • 2
    Are you aware of any way i can create such a code? I want DelegateCall to have the ability to receive a function which receives any one parameter of any type (String, bool, List...) – Jonathan Jan 16 '11 at 11:43
  • 2
    Can you recommend on any reading material how to use reflection to implement the second option? – Jonathan Jan 16 '11 at 12:10
12

Variance doesn't work that way around; you would need

DelegatedCall(obj => foo1((string)obj));

As even in 4.0 it won't believe that every object is a string.

Note that if it was foo1(object) and Action<string> (i.e. the other way around) it probably would work (in 4.0), since every string is an object.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 1
    The other way round works even prior to 4.0. When converting from a method group variance was available even in earlier versions. – CodesInChaos Jan 16 '11 at 11:35
  • Ok is there anyway i can make this work then: I want DelegateCall to have the ability to receive a function which receives any one parameter of any type (String, bool, List...). Any help would be appreciated – Jonathan Jan 16 '11 at 11:44