7

我在两个项目中使用 Visual Studio 2010。

其中一个包含一个引用 Microsoft 的 Exchange.WebServices dll(ver1.2) 以访问 ExchangeServices 的项目。我创建了一个类,其中包含一些辅助方法和包装器,以便在连接到 Exchange 服务器(通过 ExchangeService API)时执行各种任务。ExchangeService 构造函数可以接受 ExchangeVersion 的枚举,以指定服务器版本信息。所以我在我的类中创建了两个构造函数。

public class ExchangeConnector(string ver)
{
    // Property assignments
}

public class ExchangeConnector(ExchangeVersion ver)
    :this(ver.toString()) //Using(or not using) "this", doesn't seem to matter...
{ }

我创建了接受字符串参数的构造函数,因此其他项目不一定需要添加 Exchange.WebServices 库。

但后来我遇到了一个无法预料的问题。

当我在我的第二个项目(不包含对 Exchange.WebServices dll 的引用)中创建 ExchangeConnector("Exchange2007_SP1") 的实例时,Intellisense 没有选择正确的构造函数,也没有显示任何预编译错误。但是,当我强制构建时,出现以下错误:

Error: The type 'Microsoft.Exchange.WebServices.Data.ExchangeVersion' is defined
in an assembly that is not referenced. You must add a reference to assembly
'Microsoft.Exchange.WebServices, Version=14.0.0.0, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35'.

我什至没有使用带有 ExchangeVersion 枚举引用的构造函数,但它需要我引用它?

如果我用 ExchangeVersion 枚举注释掉构造函数,一切都会编译、工作,没有运行时错误。或者如果我修改重载构造函数,这样 Intellisense 就不可能混淆两者,例如:

public class ExchangeConnector(string url, ExchangeVersion ver)
{ 
  // Property assignments
}

当我调用 ExchangeConnector("Exchange2007_SP1") 时,代码编译并正常工作。没有运行时错误。

几乎就好像 VS 无法解析正确使用哪个构造函数。现在我知道我可以添加对第二个项目的引用并完成它,但我很好奇 VS 为什么要这样做。有任何想法吗?

4

2 回答 2

8

在 Scott(另一个)的启发和 CodeCaster 提供的链接之后,我想我终于找到了答案。

它是 C# 语言规范(Visual Studio .Net 2003 版)的一部分。

第 10.10 节实例构造函数中:

base(argument-listopt) 形式的实例构造函数初始化器导致调用直接基类的实例构造函数。使用参数列表和第 7.4.2 节的重载决议规则选择该构造函数。候选实例构造函数集由包含在直接基类中的所有可访问实例构造函数组成(包括任何默认构造函数,如第 10.10.4 节中所定义)。如果此集合为空,或者无法识别单个最佳实例构造函数,则会发生编译时错误。

进一步深入定义...

第 7.4.2 节重载解决方案中:

一旦确定了候选函数成员和参数列表,最佳函数成员的选择在所有情况下都是相同的:

  • 给定一组适用的候选函数成员,找到该集合中的最佳函数成员。
  • 如果该集合仅包含一个函数成员,则该函数成员是最佳函数成员。
  • 否则,如果使用第 7.4.2.2 节中的规则将每个函数成员与所有其他函数成员进行比较,则最佳函数成员是在给定参数列表方面优于所有其他函数成员的一个函数成员。
  • 如果没有一个函数成员比所有其他函数成员更好,那么函数成员调用是不明确的,并且会发生编译时错误。

更进一步...

第 7.4.2.2 节 更好的功能成员[3]

[3][http://msdn.microsoft.com/en-us/library/aa691338(v=vs.71).aspx]

给定一个具有一组参数类型 {A1, A2, ..., AN} 的参数列表 A 和两个具有参数类型 {P1, P2, ..., PN} 和 {Q1, Q2 的适用函数成员 MP 和 MQ, ..., QN}, MP 被定义为比 MQ 更好的函数成员,如果

  • 对于每个参数,从 AX 到 PX 的隐式转换并不比从 AX 到 QX 的隐式转换差,并且
  • 对于至少一个论点,从 AX 到 PX 的转换优于从 AX 到 QX 的转换。

在执行此评估时,如果 MP 或 MQ 以其扩展形式适用,则 PX 或 QX 指的是参数列表的扩展形式中的参数。

总而言之

具有相同数量参数的构造函数必须通过隐式转换来评估哪个函数成员(构造函数)会更好。

因此,为什么我需要添加对第二个项目的引用,以便编译器可以确定哪个构造函数更好。

如果构造函数没有相同数量的参数,则不需要进行评估,并且编译器不需要对第二个项目的引用。

于 2013-08-13T21:24:12.693 回答
3

对我来说,如果您的项目正在引用另一个具有重载构造函数的项目,其中其中一个构造函数接受引用的库,那么即使您没有使用该特定构造函数,您的调用项目也需要该引用才能编译。编译器不需要该引用来决定使用哪个构造函数吗?也许我遗漏了一些东西,但对我来说它工作正常似乎是合乎逻辑的。

于 2013-08-09T15:34:11.077 回答