C# 4.0 编译时错误,当错误重载包含未引用的 .NET 组件中定义的参数类型时,无法解析重载
下面是 C# 4.0 控制台程序的简单代码:
using System.DirectoryServices.Protocols;
namespace OverloadTest
{
class Program
{
static void Main(string[] args)
{
var request = new SearchRequest("", "", SearchScope.Base, null);
}
}
}
SearchRequest 有 3 个构造函数;对于本例来说,只有两个具有 4 个参数的函数很重要:
在这两个构造函数之间,它们的第一个、第三个和第四个参数具有相同类型和命名的参数。只有第二个参数不同:字符串 ldapFilter 与 XmlDocument 过滤器。
对我来说,上面的代码显然是调用构造函数,该构造函数的第二个参数声明为:string ldapFilter。
但是,如果此代码所在的项目没有对 System.XML 的引用,则编译会导致以下错误:
类型“System.Xml.XmlDocument”为在未引用的程序集中定义。您必须添加对程序集“System.Xml,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089”的引用
显然,编译器无法评估要使用哪个重载,因为错误的重载有一个参数由于缺乏对声明组件的引用而无法理解的类型。当然,编译器必须找到一个“最佳方法”来匹配我的代码,但是由于我第二个传递的参数是一个 string ,为什么编译器需要费心担心将我的代码与 匹配XmlDocument 过载?或者,由于 System.DirectoryServices.Protocols.SearchRequest 使用 XmlDocument 类型(作为构造函数参数类型);为什么编译器还没有足够了解 XmlDocument 是什么来确定字符串不是一个字符串,从而能够选择正确的重载?
我已经有两个编译时不会出现错误的解决方法:
在项目中添加对 System.XML 的引用。
命名第二个参数(因此也必须命名第三个和第四个参数),如下所示:
var request = new SearchRequest("", ldapFilter: "", searchScope: SearchScope.Base, attributeList: null);
对于我的特定情况,这是有效的,因为两个重载的第二个参数不仅在类型上不同,而且在名称上也不同(ldapFilter 与过滤器)。
如果不需要这两种解决方法,那就太好了。
Here's simple code for a C# 4.0 console program:
using System.DirectoryServices.Protocols;
namespace OverloadTest
{
class Program
{
static void Main(string[] args)
{
var request = new SearchRequest("", "", SearchScope.Base, null);
}
}
}
SearchRequest has 3 constructors; only the two which take 4 parameters matter for this example:
Between these two constructors, they have identically typed and named parameters for their first, third and forth parameters. Only the second parameters differ: string ldapFilter versus XmlDocument filter.
The above code is, obviously-to-me, calling the constructor which has its second parameter declared as: string ldapFilter.
But if the project that this code is in does NOT have a reference to System.XML then a compile results in the following error:
The type 'System.Xml.XmlDocument' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Apparently the compiler can't evaluate which overload to use because the wrong overload has a parameter of a type that is not understood due to the lack of reference to the declaring component. Sure, the compiler has to find a 'best method' to match my code, but as my second passed parameter is a string why does the compiler need to bother worrying about matching my code to the XmlDocument overload? Or alternatively, as System.DirectoryServices.Protocols.SearchRequest is using the XmlDocument type (as a constructor parameter type); why doesn't the compiler already know enough enough about what an XmlDocument is to determine that a string is not one and thus be able to choose the correct overload?
I've already got two work-arounds that compile without error:
Add a reference to System.XML in the project.
Name the 2nd parameter (and thus the 3rd and 4th too by necessity), like so:
var request = new SearchRequest("", ldapFilter: "", searchScope: SearchScope.Base, attributeList: null);
For my particular case, this works because the two overloads' second parameters differ not just in type but also in name (ldapFilter versus filter).
It'd be nice though if neither work-around was needed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于隐式转换,第二个重载可能仍然适用。
我认为在这种情况下,
字符串
将始终被选择,因为它完全匹配。但该算法可能更通用,并且当它认为需要知道其他重载的确切类型时会导致错误。有问题的情况示例:
这里,类型
B
和C
来自不同的程序集。现在,如果您调用 M(new A()),则选择哪个重载可能取决于引用的程序集。由于这种行为是不可取的,为了安全起见,编译器放弃了。就像我说的,您的示例并不完全像这样,但编译器很可能遵循相同的规则。
The second overload might still be applicable, due to implicit conversion.
I think that in this case, the
string
would be always chosen, because it matches exactly. But the algorithm is probably more general, and causes an error when it thinks it needs to know what type exactly that other overload has.Example of the problematic situation:
Here, types
B
andC
are from different assemblies. Now, if you callM(new A())
, which overload would be chosen could depend on what assemblies are referenced. Since such behavior is undesirable, the compiler gives up, to be on the safe side.Like I said, your sample is not exactly like this, but it's likely the compiler follows the same rules.