【问题标题】:Overload resolution with CType'd Enum使用 CType 枚举的重载分辨率
【发布时间】: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


【解决方案1】:

它与整数有关,特别是零。我认为这是一些未完全定义的 Option Strict 人工制品。我注意到 CType() 的默认返回类型(在 Intellisense 中)是对象。有趣的是,做任何这些事情都会消除错误:

  • 为 MyEnum 提供除整数以外的任何类型
  • AreEqual(0, MyEnum.A)
  • AreEqual(CType(1, MyEnum), MyEnum.A)

是的。疯狂的东西,找到 Heinzi!

【讨论】:

    【解决方案2】:

    诚然,我在这里有点过头了,但以下不会产生任何错误。

    AreEqual(CType(CType(0, Int16), MyEnum), MyEnum.A) 
    

    在哪里

    AreEqual(CType(CType(0, Integer), MyEnum), MyEnum.A) 
    

    确实。

    AreEqual(CType(1, MyEnum), MyEnum.A)
    

    也可以正常编译。

    如果这是废话或无用,请道歉。

    【讨论】:

      【解决方案3】:

      我认为你的问题是你没有限制你的泛型类型 T。所以它也可能是一个对象。

      即如果 T 是 object 类型,那么当编译器翻译成通用中间语言时,它们是相同的:

       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
      

      我不明白为什么你需要两者。 T 将迎合对象。所以只要放下第二个,一切都应该仍然有效吗?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-06
        • 2015-08-12
        • 2019-12-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多