【发布时间】:2015-03-05 15:41:04
【问题描述】:
考虑以下最小示例:
Module Module1
Private Enum MyEnum
A
End Enum
Public Sub Main(args As String())
AreEqual(CType(0, MyEnum), MyEnum.A) ' Error here
End Sub
Private Function AreEqual(Of T)(item1 As T, item2 As T) As Boolean
Return False
End Function
Private Function AreEqual(item1 As Object, item2 As Object) As Boolean
Return False
End Function
End Module
由于某种奇怪的原因,在标有“此处错误”的行中重载解析失败:
错误 6 重载解析失败,因为没有可访问的 'AreEqual' 最适合这些参数:
Private Function AreEqual(item1 As Object, item2 As Object) As Boolean:不是很具体。
Private Function AreEqual(Of MyEnum)(item1 As MyEnum, item2 As MyEnum) As Boolean:不是很具体。
为什么第二个函数不是“最具体的”?CType(0, MyEnum) 和MyEnum.A 都应该是静态类型为MyEnum 的表达式。
有趣的是,我只能通过投射枚举来重现这个问题。 AreEqual(CType(0, Int32), 0) 和 AreEqual(MyEnum.A, MyEnum.A) 都编译没有问题。
我知道如何解决这个问题。我知道我可以使用 AreEqual(Of MyEnum)(...)。那不是问题。我很好奇为什么会发生这种情况。一些编译器错误?有趣的是,相应的 C# 代码确实工作:
enum MyEnum { A, B }
static void Main(string[] args)
{
AreEqual((MyEnum)0, MyEnum.A);
}
static bool AreEqual<T>(T item1, T item2) { return false; }
static bool AreEqual(object item1, object item2) { return false; }
【问题讨论】:
-
仅作记录:是的,我知道
CType(0, Int32)是无操作的,是的,我当然使用Option Strict On。是的,我知道我的两个函数都没有做任何有用的事情。这只是一个 mcve 旨在演示特定问题。 -
希望language specification 允许某人确定这是编译器错误还是规则的不幸但正确的副作用。但不是我——我认为 C# 的推理和重载规则很复杂,但与 VB 所提供的相比,它没什么。考虑到它还必须考虑动态类型,这在某种程度上是意料之中的。
-
尝试改用 DirectCast(我会尝试,但我现在可以移动)。我猜这可能会奏效。
-
不会,Roslyn 会在 VSnext 中编译。
-
我想知道这个原始错误是否与这个 C#“怪癖”有关。 stackoverflow.com/questions/14224465/…(请务必阅读接受的答案和 Lippert 的答案。)
标签: c# vb.net casting enums overload-resolution