VB Compiler не делает неявных приведений к Object? - PullRequest
2 голосов
/ 10 апреля 2011

У меня недавно была странная проблема с одним из моих API-интерфейсов. По существу, по какой-то причине при использовании с кодом VB компилятор VB не выполняет неявное приведение к объекту при попытке вызвать метод ToString ().

Ниже приведен пример минимального кода, во-первых, на C #, а во-вторых, на VB:

    Graph g = new Graph();
    g.LoadFromEmbeddedResource("VDS.RDF.Configuration.configuration.ttl");

    foreach (Triple t in g.Triples)
    {
        Console.WriteLine(t.Subject.ToString());
    }

Выше компилируется и работает нормально, а ниже нет:

    Dim g As Graph = New Graph()
    g.LoadFromEmbeddedResource("VDS.RDF.Configuration.configuration.ttl")

    For Each t As Triple In g.Triples
        Console.WriteLine(t.Subject.ToString())
    Next

Второй пример VB дает следующее исключение компилятора:

Не удалось разрешить перегрузку, потому что нет Доступный ToString принимает это количество аргументов.

Похоже, это связано с тем, что тип свойства t.Subject, которое я пытаюсь записать в консоль, явно определило ToString() методы, которые принимают параметры. Компилятор VB, похоже, ожидает использования одного из них, и, похоже, неявно приводит его к Object и использует стандартный метод Object.ToString(), в то время как компилятор C # делает.

Есть ли способ обойти это, например, опция компилятора VB или лучше всего просто убедиться, что тип свойства (который в данном примере является интерфейсом) явно определяет непараметрический метод ToString(), чтобы обеспечить совместимость с VB?

Редактировать

Вот дополнительные сведения, запрошенные Lucian

  1. Graph - это реализация интерфейса, но на самом деле это не имеет значения, поскольку именно интерфейс INode , тип которого возвращает t.Subject, является проблемой.
    INode определяет две перегрузки для ToString(), каждая из которых принимает параметры
  2. Да, это ошибка времени компиляции
  3. Нет, я не использую скрытие по имени, все API написаны на C #, поэтому я не мог генерировать такого рода API, если бы захотел

Обратите внимание, что с тех пор я добавил явную непараметризованную перегрузку ToString() к интерфейсу, которая исправила проблему для пользователей VB.

Ответы [ 2 ]

4 голосов
/ 28 июня 2011

RobV, я ведущий специалиста по VB, поэтому я должен ответить на ваш вопрос, но мне понадобятся некоторые разъяснения, пожалуйста ...

  • Какие перегрузки определены в «Графике»? Это помогло бы, если бы вы могли сделать отдельное воспроизведение. Трудно объяснить поведение перегрузки, не зная кандидатов перегрузки:)

  • Вы сказали, что произошел сбой с " исключение компилятора ". Это на самом деле не существует. Вы имеете в виду «ошибку времени компиляции»? Или «исключение во время выполнения»?

  • Нужно проверить, полагаетесь ли вы на какое-либо поведение «скрывать по имени» против «скрывать по сигналу». Компилятор C # только когда-либо испускает API "Hide-By-Sig"; Компилятор VB может генерировать любой из них в зависимости от того, используете ли вы ключевое слово "Shadows".

  • Алгоритм перегрузки C # предназначен для повышения уровня иерархии наследования до уровня, пока не будет найдено возможное совпадение; Алгоритм перегрузки VB заключается в одновременном рассмотрении всех уровней иерархии наследования, чтобы определить, какой из них наилучшим образом соответствует. Это все немного теоретически, но с небольшим самодостаточным воспроизведением вашей проблемы я мог бы объяснить, что это означает на практике.

Ганс, я не думаю, что ваше объяснение правильное. Ваш код выдает ошибку во время компиляции "BC30455: Аргумент не указан для параметра 'mumble' ToString". Но RobV испытал «Сбой при разрешении перегрузки, потому что ни один из доступных ToString не принимает это количество аргументов».

2 голосов
/ 10 апреля 2011

Вот репродукция этого поведения. Также показан обходной путь, приведенный с помощью CObj ():

Module Module1
    Sub Main()
        Dim itf As IFoo = New CFoo()
        Console.WriteLine(itf.ToString())        '' Error BC30455
        Console.WriteLine(CObj(itf).ToString())  '' Okay
    End Sub
End Module

Interface IFoo
    Function ToString(ByVal mumble As Integer) As String
End Interface

Class CFoo
    Implements IFoo
    Function ToString1(ByVal mumble As Integer) As String Implements IFoo.ToString
        Return "foo"
    End Function
End Class

Я думаю, что это аннотировано в спецификации языка VB.NET, глава 11.8.1 «Разрешение перегруженного метода»:

Обоснование этого правила что если программа свободно напечатана (то есть большинство или все переменные объявлен как объект), перегрузка разрешение может быть трудным, потому что все преобразования из объекта сужение. Вместо того, чтобы иметь разрешение перегрузки не удается во многих ситуации (требующие строгого аргументы вызова метода), разрешение соответствующее перегружено метод для вызова откладывается до запуска время. Это позволяет свободно набирать призыв к успеху без дополнительных слепки.

неудачный побочный эффект этого, однако, что выполнение поздний вызов требует приведения вызвать цель для объекта. В случае значение структуры, это означает, что значение должно быть упаковано во временное. Если в конце концов, вызванный метод пытается изменить поле структуры, это изменение будет потеряно, как только метод возвращается.

Интерфейсы исключены из этого специальное правило, потому что позднее связывание всегда решает против членов класс времени выполнения или тип структуры, которые могут иметь разные имена, чем члены интерфейсов они реализовать.

Не уверен. Я бы транслитерил это так: VB.NET - это свободно типизированный язык, где многие ссылки на объекты обычно имеют позднюю привязку. Это делает опасным разрешение перегрузки метода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...