无法将“方法组”转换为“System.Action<object>”错误

54
我已经创建了下面的函数:
public void DelegatedCall(Action<Object> delegatedMethod)

并定义了以下方法

public void foo1(String str) { }

然而,当我尝试使用foo1调用DelegateCall时:

DelegatedCall(foo1);

我遇到了以下编译器错误:

参数 1: 无法从 "方法组" 转换为 "System.Action<object>"

这个错误的原因是什么,我该如何纠正它?不幸的是,将foo1强制转换为Action并不可行。


1
相关:C#中的方法组是什么? - DavidRR
2个回答

36
DelegatedCall 需要一个委托作为参数,该委托可以接受任何 object 类型的参数。但是你传递给 DelegatedCallfoo1 函数只能处理 string 类型的参数。因此,类型转换不安全,无法进行。

输入参数是contra-variant,但你的代码需要covariance。(详见 Difference between Covariance & Contra-variance.)

你可以将 DelegatedCall 设为泛型:

DelegatedCall<T>(Action<T> action)

...或者将其委托给任何代表:

DelegatedCall(Delegate action)

但是实现它很丑陋,需要使用反射。而且它也不能在编译时验证函数是否只有一个参数。


2
你是否知道我可以创建这样的代码的方法?我希望DelegateCall能够接收一个接收任何类型(String、bool、List...)中任何一个参数的函数的功能。 - Jonathan
2
你能推荐一些阅读材料,教如何使用反射来实现第二个选项吗? - Jonathan

12

方差的计算不是这样的;你需要

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

即使在4.0版本中,它也不会认为每个对象都是字符串。

请注意,如果参数是foo1(object)而委托类型是Action<string>(也就是说参数类型和委托类型相反),那么它可能会在4.0版本中工作,因为每个字符串都是一个对象。


1
另一种方法甚至在4.0之前就可以使用。当从方法组进行转换时,即使在早期版本中也可以使用方差。 - CodesInChaos
好的,有没有什么办法可以让这个工作呢:我想让DelegateCall能够接收一个函数,该函数接收任何一种类型(String、bool、List...)的任何一个参数。任何帮助都将不胜感激。 - Jonathan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接