Действие, ведущее себя как Func в VB.NET - PullRequest
3 голосов
/ 22 сентября 2011

Сегодня я наблюдал очень странное поведение в VB.NET.Код, о котором я говорю, следующий:

Option Strict On
Option Explicit On

Module Module1

    Sub Main()
        Dim thisShouldBeSet = False

        DoSomething(Function() thisShouldBeSet = True)

        If Not thisShouldBeSet Then
            Throw New Exception()
        End If

        Console.WriteLine("yaay")
    End Sub

    Sub DoSomething(action As Action)
        action.Invoke()
    End Sub
End Module

Я знаю, что код сам по себе имеет недостатки, потому что я должен использовать:

DoSomething(Sub() thisShouldBeSet = True)

Вместо:

DoSomething(Function() thisShouldBeSet = True)

Но я нахожу очень странным, что даже при Option Strict и Option Explicit On компиляция позволяет мне скомпилировать этот код.

Что еще более странно, так это то, что при выполнении кода действие фактически ведет себя как Func (логического).

Может кто-нибудь дать мне правильное объяснение, почему это разрешено в VB.СЕТЬ?Это ошибка компилятора / времени выполнения?

Ответы [ 2 ]

8 голосов
/ 22 сентября 2011

Почему он не должен позволять вам компилировать код? thisShouldBeSet = True - допустимое сравнение, возвращающее значение False (потому что thisShouldBeSet <> True). Помните, что = в VB может означать как = (назначение), так и == (сравнение) в C #, в зависимости от контекста.

Чтобы уточнить, Sub() thisShouldBeSet = True будет сокращением для

Sub Anonymous()
    thisShouldBeSet = True           ' Assignment
End Sub

, тогда как Function() thisShouldBeSet = True - сокращение от

Function Anonymous() As Boolean
    Return thisShouldBeSet = True    ' Comparison
End Sub

В VB явно разрешено использовать функцию с возвращаемым значением в качестве Action. Из документации делегата System.Action (выделено мной):

В C # метод должен возвращать void. В Visual Basic он должен быть определен конструкцией Sub… End Sub. Это также может быть метод, который возвращает значение, которое игнорируется.

1 голос
/ 22 сентября 2011

Здесь происходит то, что вы создаете замыкание .

Ваш метод lamdba ведет себя как функция, а не как sub в обоих случаях, поскольку вы захватили / закрыли переменную thisShouldBeSet из метода Main, а выражение thisShouldBeSet = True для Sub интерпретирует оператор =как присваивание , скорее, сравнение.

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