【问题标题】:How can I get a method reference for an instance method with a dynamically bound target如何获取具有动态绑定目标的实例方法的方法引用
【发布时间】:2016-05-30 12:39:09
【问题描述】:

在 C# 中,我们可以通过对静态方法或实例方法的方法引用来实例化委托。示例:

Func<object, object, bool> refEquals = Object.ReferenceEquals;  // target = null
Func<string> toStr = new Object().ToString; // target = new Object()

对于后者,代表的目标是new Object(),而前者的目标是null

但是,如果没有预定义的target,如何为ToString 方法引用实例化一个委托?在这种情况下,我希望ToString 的目标将绑定到代表的参数。这可能很有用,例如,对 IEnumerable&lt;T&gt; 的所有项目调用某个实例方法:

Func<object, string> toStr = Object.ToString; // the target (this) would be the Func’s argument
IEnumerable<T> dataSrc = ...
IEnumerable<String> dataSrc = dataSrc.Select(toStr);

但是,第一行无法编译:

错误 CS0123:“ToString”没有重载匹配委托“System.Func”

Java 8 通过Reference to an Instance Method of an Arbitrary Object 提供此功能。如何在 .Net 中实现同样的功能?


我知道我们可以使用 lambda 表达式来超越这个限制,例如:

 Func<Object, String> toStr = item => item.ToString();

但是,这会导致调用ToString 实例方法的进一步间接,因此我不认为这种解决方法是解决我的问题的有效解决方案。

【问题讨论】:

  • 我不懂java,但在C# 中,如果需要,您必须将对象实例传递给委托。从未听说过 arbitrary object 或类似的东西。通过反射(使用StackFrame),您可以获得方法名称等,但不多,那将是 lambda(您试图避免)。

标签: c# c#-4.0 lambda delegates


【解决方案1】:

通过 Reflection,您可以获得与 Java 8 中描述的行为等效的行为。您可以创建具有 null 目标的 Delegate 实例并将其第一个参数动态绑定到 @ 987654322@方法参数。对于您的示例,您可以通过以下方式创建 toStr 委托:

MethodInfo methodToStr = typeof(object).GetMethod("ToString");
Func<Object, String> toStr = (Func<Object, String>) Delegate.CreateDelegate(
            typeof(Func<Object, String>),
            methodToStr);

【讨论】:

  • 我认为真正的答案是,“在 c# 中,没有 lambda 或辅助方法,你不能”。虽然这是最接近的 - 但一般情况下有AmbiguousMatchException的风险。
  • @Tewr 您可能会在委托实例化时遇到该异常。
猜你喜欢
  • 2014-09-04
  • 1970-01-01
  • 2013-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多