0

I updated an AutoMapper V3.3.1 to V6.1.1 and much to my surprise, after putting all CreateMaps() in a profile, it actually worked perfectly right out of the gate – almost scary for me.

The problem that I am having is that it IS working with the code below as is suggested in the AutoMapper documentation:

Private Sub InitiatizeAutoMapper()
    Mapper.Initialize(Function(cfg)
                          cfg.AddProfile(Of MappingProfile)()
                      End Function)
End Sub

But the code issues a warning:

Warning BC42105 Function '<anonymous method>' doesn't return a value on all code paths. A null reference exception could occur at run time when the result is used.

If I add a Return to the Lambda like:

Private Sub InitiatizeAutoMapper()
    Mapper.Initialize(Function(cfg)
                          Return cfg.AddProfile(Of MappingProfile)()
                      End Function)
End Sub

I then get the following error:

Error   BC30518 Overload resolution failed because no accessible 'Initialize' can be called with these arguments:
    'Public Shared Overloads Sub Initialize(config As Action(Of IMapperConfigurationExpression))': Expression does not produce a value.
    'Public Shared Overloads Sub Initialize(config As Action(Of IMapperConfigurationExpression))': Expression does not produce a value.
    'Public Shared Overloads Sub Initialize(config As MapperConfigurationExpression)': Lambda expression cannot be converted to 'MapperConfigurationExpression' because 'MapperConfigurationExpression' is not a delegate type.

Now - if I make it a Sub instead of a function, it all works well with no errors like this:

Private Sub InitiatizeAutoMapper()
    Mapper.Initialize(Sub(cfg)
                          cfg.AddProfile(Of MappingProfile)()
                      End Sub)
End Sub

I know that this will probably be a head-slapper but I am trying to follow the documentation and am afraid to release this into production in that I might be missing something.

EDIT:

I chose to break down the multiline lambda to make it a little easier for me, which also avails IntelliSense options quite handily for future enhancement. While it is probably not the "coolest" code, I find it very readable.

Private Sub InitiatizeAutoMapper()
    Dim config As New Configuration.MapperConfigurationExpression : With config
        .AddProfile(Of MappingProfile)()
    End With
    Mapper.Initialize(config)
End Sub
HumbleBeginnings
  • 1,009
  • 10
  • 22
  • Thanks @jmcilhinney for your reply. Of course I know the difference between a Sub and a Function, and I guess that I've only been exposed previously to Function Delegates so I will have to brush up a bit on Action Delegates which now makes perfect sense. It was the end of a long day and I guess that I wasn't able to see the forest for the trees. I was converting C# to VB as well from https://github.com/AutoMapper/AutoMapper/wiki/Static-and-Instance-API and I guess nothing was sinking in. I've edited my OP to show the course I took. Seriously though - thanks for your direction. – HumbleBeginnings Oct 29 '17 at 16:26

1 Answers1

2

The whole point of a Function is that it returns something. In your first code snippet, what is your anonymous function returning? It isn't returning anything because it has no Return statement. There's no point arbitrarily adding a Return statement if you don't actually have anything to return and you can't return the result of AddProfile if that doesn't return anything itself. Basically, your lambda doesn't return anything and what do we call a method that doesn't return anything? It's a Sub.

You'll notice in the error message you posted that the Initialize method overloads that take a delegate as an argument are expecting an Action, not a Func. Action delegates are created with a Sub while a Function is used to create a Func delegate.

jmcilhinney
  • 50,448
  • 5
  • 26
  • 46