Разрешение перегрузки с помощью CType'd Enum

Рассмотрим следующий минимальный пример:

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.

Интересно, что я могу воспроизвести эту проблему только с помощью Enum. AreEqual(CType(0, Int32), 0) и AreEqual(MyEnum.A, MyEnum.A) скомпилируются без проблем.

Я знаю, как это исправить. Я знаю, что могу просто использовать AreEqual(Of MyEnum)(...). Дело не в этом. Мне любопытно, почему это происходит. Некоторая ошибка компилятора? Интересно, что соответствующий код С# работает:

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; }

Ответ 1

Это связано с целыми числами, в частности с нулем. Я думаю, что это не совсем определенный вариант Strict artefact. Я отмечаю тип возвращаемого значения по умолчанию (в Intellisense) для объекта CType() - это объект. Интересно, что любое из этих действий устраняет ошибку:

  • Предоставление MyEnum любого типа, кроме целого
  • AreEqual (0, MyEnum.A)
  • AreEqual (CType (1, MyEnum), MyEnum.A)

Угу. Сумасшедший материал, хорошая находка Хейнзи!

Ответ 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 имеет объект типа, то они идентичны при переходе на общий промежуточный язык компилятором:

 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 будет обслуживать объект. Так что просто опустите второй, и все должно работать?