扩展方法调用不会编译,但对相同代码的静态方法调用会编译

2023-12-25

库 A 使用 C# 扩展方法调用库 B。

我从 C# 编译器中收到一个奇怪的错误:

类型“System.Windows.Forms.Control”是在程序集中定义的 没有被引用。您必须添加对程序集的引用 'System.Windows.Forms,版本=4.0.0.0

库 A 或 B 都不依赖于System.Windows.Forms.Control,A 也不依赖于System.Windows.Forms.Control. System.Windows.Forms.Control仅从同一解决方案中的另一个项目引用。

奇怪的是,如果我将调用语法更改为静态方法,它就会成功编译。

//static method syntax works fine
var leads = SourceLeadConfigurationHelper.GetLeads(enLeadSystem);

//extension method syntax cause error
//error The type 'System.Windows.Forms.Control' is defined in an assembly that is not referenced. 
var leads = enLeadSystem.GetLeads();

扩展方法如下所示:

public static class SourceLeadConfigurationHelper
{      
    public static IList<ChannelID> GetLeads(this LeadSystem leadSystem);
    public static IList<ChannelID> GetLeads(this SourceLeadConfiguration slc);
    public static IList<ChannelID> GetLeads(LeadSystem leadSystem, bool throwException);
}

所以你会发现检测使用哪个扩展没有问题。LeadSystem是一个枚举,SourceLeadConfiguration是一个类。

我有 Visual Studio 2013 更新 5、.NET Framework 4.0。


这是对 C# 编译器行为的一致抱怨,让程序员非常抓狂。不幸的是,没有规范的问答,每个案例都是不同的。第一份报告在 VS2012/.NET 4.5 时间范围内开始出现。编译器过去并没有这样做,它听起来像是一个错误修复,其影响比预期更大。我们也没有经常听到它,大多数程序员只是按照错误消息中的指导并添加程序集引用。你也应该如此,它可以轻松解决问题。

尝试在这里描述一下它的特征。它与扩展方法没有直接关系,此行为特定于方法重载解析。扩展方法只是它的一个特例,当然是一个棘手的情况。

找到方法重载匹配并不是特别棘手,当重载不明确时,它会生成一条不错的错误消息,这才是问题所在。关于更改的行为非常清楚的一件事是编译器现在更加彻底。它坚持要知道一切关于参数的类型。即使程序员很清楚传递的参数不可能与另一个未引用的程序集中的类型匹配。但编译器对此很顽固,如果它不知道类型,那么它会坚持你添加引用。

扩展方法很棘手,因为可能有很多,而不仅仅是您(显然)期望选择的 SourceLeadConfigurationHelper.GetLeads() 。一次集会might定义其他扩展方法,它们只是might向 SourceLeadConfiguration 类型添加更多扩展方法。如果编译器知道程序集存在,但不知道它是什么样子,因此无法知道它可能包含哪些扩展方法,那么它会抱怨。请注意,这解释了为什么直接调用静态方法时不会出现错误,编译器不需要去寻找扩展。

您肯定可以猜到编译器如何找到 System.Windows.Forms 程序集。它是由另一个程序集引入的,即您提到但没有描述的程序集。诊断结果是 System.Windows.Forms.Control 类型在该程序集的元数据中泄漏。通常作为公共方法的参数或返回类型。您必须在源代码中进行一些挖掘才能找到它,否则您可以轻松消除它。


关于扩展方法的另一个细节是might与此相关的是,ExtensionAttribute 类型在 .NET 4.5 中从 System.Core.dll 移至 mscorlib.dll。这是一项相当重大的更改,并且当程序员没有正确构建程序集时会导致很多问题。如果您的目标是 .NET 4.0,那么您需要仔细检查这一点,详细信息are here https://stackoverflow.com/a/13750130/17034.


希望您能从引用 Winforms 的程序集中找到它。如果没有,或者您无法消除暴露,那么添加引用实际上就足以让编译器满意。

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

扩展方法调用不会编译,但对相同代码的静态方法调用会编译 的相关文章

  • WPF DataGrid 多选

    我读过几篇关于这个主题的文章 但很多都是来自 VS 或框架的早期版本 我想做的是从 dataGrid 中选择多行并将这些行返回到绑定的可观察集合中 我尝试创建一个属性 类型 并将其添加到可观察集合中 它适用于单个记录 但代码永远不会触发多个
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • 如何在 C# 中打开 Internet Explorer 属性窗口

    我正在开发一个 Windows 应用程序 我必须向用户提供一种通过打开 IE 设置窗口来更改代理设置的方法 Google Chrome 使用相同的方法 当您尝试更改 Chrome 中的代理设置时 它将打开 Internet Explorer
  • 如何从本机 C(++) DLL 调用 .NET (C#) 代码?

    我有一个 C app exe 和一个 C my dll my dll NET 项目链接到本机 C DLL mynat dll 外部 C DLL 接口 并且从 C 调用 C DLL 可以正常工作 通过使用 DllImport mynat dl
  • 如何在 C++ 中标记字符串?

    Java有一个方便的分割方法 String str The quick brown fox String results str split 在 C 中是否有一种简单的方法可以做到这一点 The 增强分词器 http www boost o
  • 对类 static constexpr 结构的未定义引用,g++ 与 clang

    这是我的代码 a cp p struct int2 int x y struct Foo static constexpr int bar1 1 static constexpr int2 bar2 1 2 int foo1 return
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • 如何获取 EF 中与组合(键/值)列表匹配的记录?

    我有一个数据库表 其中包含每个用户 年份组合的记录 如何使用 EF 和用户 ID 年份组合列表从数据库获取数据 组合示例 UserId Year 1 2015 1 2016 1 2018 12 2016 12 2019 3 2015 91
  • 结构体的内存大小不同?

    为什么第一种情况不是12 测试环境 最新版本的 gcc 和 clang 64 位 Linux struct desc int parts int nr sizeof desc Output 16 struct desc int parts
  • 为什么使用小于 32 位的整数?

    我总是喜欢使用最小尺寸的变量 这样效果就很好 但是如果我使用短字节整数而不是整数 并且内存是 32 位字可寻址 这真的会给我带来好处吗 编译器是否会做一些事情来增强内存使用 对于局部变量 它可能没有多大意义 但是在具有数千甚至数百万项的结构
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • C# 中最小化字符串长度

    我想减少字符串的长度 喜欢 这串 string foo Lorem ipsum dolor sit amet consectetur adipiscing elit Aenean in vehicula nulla Phasellus li
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使
  • 使用 WGL 创建现代 OpenGL 上下文?

    我正在尝试使用 Windows 函数创建 OpenGL 上下文 现代版本 基本上代码就是 创建窗口类 注册班级 创建一个窗口 choose PIXELFORMATDESCRIPTOR并设置它 创建旧版 OpenGL 上下文 使上下文成为当前

随机推荐