为什么尝试使用动态参数调用扩展方法时出现错误 CS1973

2024-04-19

考虑以下代码:

internal static class Program
{
    public static string ExtensionMethod(this string format, dynamic args)
    {
        return format + args.ToString();
    }

    private static void Main()
    {
        string test = "hello ";
        dynamic d = new { World = "world" };

        // Error CS1973  'string' has no applicable method named 'ExtensionMethod'
        //                but appears to have an extension method by that name. 
        //               Extension methods cannot be dynamically dispatched. 
        //               Consider casting the dynamic arguments or calling
        //               the extension method without the extension method syntax.
        var result = test.ExtensionMethod(d);

        // this syntax works fine
        var result2 = Program.ExtensionMethod(test, d);

        // for whatever reason, this works, too!
        var result3 = test.ExtensionMethod((object)d);

        // even this works...
        var result4 = test.ExtensionMethod(new { World = "world" });

        Console.WriteLine(result);
        Console.ReadLine();
    }
}

我不明白这背后的逻辑。我确实明白,first扩展方法的参数不能是动态的。我什至会理解,如果我传递了一些东西,调度将无法正常工作but另一个动态。但显然确实如此。它可以将其他类型映射到动态。但是当我通过时调度不起作用精确类型方法要求?它无法映射dynamic to dynamic?这对我来说没有意义。

我可以阅读并理解该错误,并且我显然知道解决方法,但任何人都可以启发我why这个错误存在吗?我看不到的更深层次的问题是什么?


有几个现有问题解释了为什么第一个参数(string)在这种情况下不能是动态的 -如何调用动态类型的扩展方法? https://stackoverflow.com/questions/5270782/how-to-call-an-extension-method-of-a-dynamic-type显示将分机呼叫转换为常规呼叫的解决方法。确实,它适用于我的情况。

还有很多“什么是CS1973”问题(https://stackoverflow.com/search?q=CS1973 https://stackoverflow.com/search?q=CS1973)但大多数人还是首先处理(this Xxxx)参数是dynamic(这听起来公平失败)或者只是表现出相同的行为而不解释为什么喜欢“System.Web.Mvc.HtmlHelper”没有名为“Partial”的适用方法 https://stackoverflow.com/questions/28465114/system-web-mvc-htmlhelper-has-no-applicable-method-named-partial(在强类型对象上调用已知扩展,但传递dynamic作为第二个参数)。

但这并不能解释为什么当可以在编译时确定单一扩展方法时仍然无法使用,这就是这个问题的目的。


因为扩展方法绑定在编译时间。它们本质上被编译器转换为静态方法调用,这意味着

var result = test.ExtensionMethod(d);

被编译器转换为

var result = Program.ExtensionMethod(test, d);

When any的参数是dynamic, then all绑定被推迟到运行时。运行时绑定器当前不支持扩展方法的绑定,编译器知道这一点,并会生成错误。

我什至会理解,如果我传递的是另一种动态之外的东西,调度是否会不起作用。

请记住dynamic (like var) 不是一个type。它只是意味着“我不知道这在编译时是什么类型 - 我会让动态运行时查看actual键入并确定如何处理它。

所以当你说:

dynamic d = new { World = "world" };

d不是一个dynamic"。在运行时,值d将是匿名类型。

Could the dynamic binder support extension methods? Probably, but to date*, the added value has not been worth the cost (relative to other things that could be added) to design, implement, test, ship, and support such a feature. If you feel this would be a valuable addition to the framework, then feel free to submit a suggestion at http://connect.microsoft.com/ http://connect.microsoft.com/.

我还要注意的是,没有必要使用dynamic在你的(尽管是人为的)场景中。如果您使用,您会得到完全相同的行为(具有扩展方法支持)object代替dynamic(并将扩展方法移至静态类):

public static string ExtensionMethod(this string format, object args)
{
    return format + args.ToString();
}
private static void Main()
{
    string test = "hello ";
    object d = new { World = "world" };

    // Error CS1973  'string' has no applicable method named 'ExtensionMethod'
    //                but appears to have an extension method by that name. 
    //               Extension methods cannot be dynamically dispatched. 
    //               Consider casting the dynamic arguments or calling
    //               the extension method without the extension method syntax.
    var result = test.ExtensionMethod(d);

    // this syntax works fine
    var result2 = Program.ExtensionMethod(test, d);

    // for whatever reason, this works, too!
    var result3 = test.ExtensionMethod((object)d);

    // even this works...
    var result4 = test.ExtensionMethod(new { World = "world" });

    Console.WriteLine(result);
    Console.ReadLine();
}

* at least in 2011 problem of finding the method to call in this case was considered too hard - see Eric Lippert's answer - https://stackoverflow.com/a/5313149/477420 https://stackoverflow.com/a/5313149/477420: " ...That means that in order to get a dynamic extension method invocation resolved correctly, somehow the DLR has to know at runtime what all the namespace nestings and using directives were in your source code. We do not have a mechanism handy for encoding all that information into the call site..."

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么尝试使用动态参数调用扩展方法时出现错误 CS1973 的相关文章

  • 为什么隐式类型转换没有警告?

    我终于发现了程序中的一个错误 该错误是由返回类型的隐式类型转换引起的 即使g Wall对此没有任何警告 我想知道是否有什么办法可以快速找出这种无意识的错误 include
  • Boost.Intrusive 和 unordered_map

    我希望使用侵入性的 unordered map 由于某种原因 库中只有一个 unordered set 还有一个侵入式哈希表 但我不确定它是否具有相同的功能 而且它没有相同的接口 我错了吗 我错过了 unordered map 链接吗 如果
  • Windows 上任何单个进程可以寻址的最大内存量

    Windows 版本的内存限制 http msdn microsoft com en us library windows desktop aa366778 28v vs 85 29 aspx回答 Windows 上任何单个进程可以寻址的最
  • 这些比较应该返回什么?

    我有一个使用 string compare string string 对某些值进行排序的应用程序 我不明白的是为什么 1022 比较小于 10 23 而 10 23 比较小于 1024 是否有特定于 值的东西导致了这个结果 string
  • 未初始化成员的警告在 C++11 上消失

    我编译这个简单的程序 include
  • 使用 SFML 绘制文本时出现段错误

    我做了一个Button应该绘制一些顶点和字符串的类RenderWindow 这是删除了不相关部分的代码 here http pastebin com 4a5RuS2y是完整的代码 namespace game class Button pu
  • 如何吞咽……有具体原因的异常

    在这个方法中 public static void Detach try using var master new DataContext Data Source LocalDB MSSQLLocalDB Initial Catalog m
  • 与智能指针的返回类型协方差

    在 C 中我们可以这样做 struct Base virtual Base Clone const virtual Base struct Derived Base virtual Derived Clone const overrides
  • 欢迎消息在网络聊天中不可见,但可以在模拟器中使用

    IConversationUpdateActivity update message using var scope Microsoft Bot Builder Dialogs Internals DialogModule BeginLif
  • 再次对存储库和持久性一无所知

    这就是我要做的 我有一个通用的存储库类Repository
  • 编译使用Basler相机的程序

    我正在尝试使用 Basler 相机捕获图像的 C 程序来工作 我拿到 来自制造商的代码 它应该 非常容易使用 但是 链接它有 成为一场噩梦 我的 C 时代已经过去了 最近只使用 Matlab 所以我可能会犯一些愚蠢的错误 但请赐教 代码如下
  • Compact Framework 3.5 上的 System.Data.SQLite 问题

    我在我的紧凑框架应用程序中使用 sqlite 来记录系统中的事件 我也在使用系统 数据 SQLite http sqlite phxsoftware com 该事件具有描述其发生时间的时间戳 我将此时间戳记作为刻度存储在我的表中 除此列外
  • BackgroundWorker 如何决定在哪个线程上运行 RunWorkerCompleted 处理程序?

    我试图弄清楚 BGW 在工作完成后如何决定运行 RunWorkerCompleted 处理程序的线程 我的初始测试使用 WinForm 应用程序 在 UI 线程上 我开始bgw1 RunWorkerAsync 然后我尝试开始bgw2 Run
  • 在 C# 中同步闪烁标签

    我创建了一个BlinkingLabel类 源自Forms Label 其中有一个Forms Timer这允许我启用和禁用闪烁效果 我创建了 4 个标签BlinkingLabel类型 我的问题是 如果所有 4 个标签在不同时间闪烁 则闪烁效果
  • 显示具有相同节点值的多个 XML 数据条目

    我有一个 XML 文档 其中包含课程信息 如下所示
  • STL迭代器是否保证集合更改后的有效性?

    假设我有某种集合 并且我在它的开头获得了一个迭代器 现在假设我修改了该集合 无论集合或迭代器的类型如何 我仍然可以安全地使用迭代器吗 为了避免混淆 以下是我讨论的操作顺序 获取集合的迭代器 修改集合 显然 不是其中的元素 而是集合本身 使用
  • AZURE:workerrole 中的异步 Run()

    我有一个异步任务 async Task UploadFiles 我想在 azure 工作者角色的 Run 方法中调用 UploadFiles 上的 等待 但 await 仅适用于声明为异步的方法 那么我可以使 Run 方法异步 如下所示 p
  • 指针 (*argv[]) 的指针的指针算术?

    我知道foo bar 等于 foo bar 但是什么是 foo bar 等于 例如访问 argv 2 我对这一点的理解有些困惑 我认为可能是这样的 foo bar 但我不确定 如果这是一个简单的答案 我深表歉意 a b 相当于 a b 由于
  • 制作一个未知大小的数组 C# [重复]

    这个问题在这里已经有答案了 可能的重复 C 中未知长度的数组 https stackoverflow com questions 599369 array of an unknown length in c sharp 我想创建一个程序 用
  • C# StreamReader 使用分隔符保存到数组

    我有一个文本文件 其中包含制表符分隔的数据 我在 C 应用程序中需要的是从文本文件中读取一行并将它们保存到一个数组中 在每个位置将它们分开 t 然后我对下一行做同样的事情 My code StreamReader sr new Stream

随机推荐