Question

The following VB.NET code works:

Dim request As Model.LearnerLogbookReportRequest = New Model.LearnerLogbookReportRequest
request.LearnerIdentityID = Convert.ToInt32(Session("identityID"))
request.EntryVersion = LearnerLogbookEntryVersion.Full

Dim reportRequestService As IReportRequestService = ServiceFactory.GetReportRequestService(ServiceInvoker.LearnerLogbook)
        reportRequestservice.SaveRequest(request)

The following C# code fails to compile:

LearnerLogbookReportRequest request = new LearnerLogbookReportRequest();
request.LearnerIdentityID = theLearner.ID;
request.EntryVersion = LearnerLogbookEntryVersion.Full;

IReportRequestService reportRequestService = ServiceFactory.GetReportRequestService(ServiceInvoker.LearnerLogbook);

reportRequestService.SaveRequest(ref request);

The LearnerLogbookReportRequest is declared as:

Public Class LearnerLogbookReportRequest
    Inherits AbstractReportRequest

Error:

Error   11  Argument 1: cannot convert from 'ref RACQ.ReportService.Common.Model.LearnerLogbookReportRequest' to 'ref RACQ.ReportService.Common.Model.AbstractReportRequest'    C:\p4projects\WEB_DEVELOPMENT\SECURE_ASPX\main-dev-codelines\LogbookSolution-DR6535\RACQ.Logbook.Web\Restful\SendLogbook.cs 64  50  RACQ.Logbook.Web

Why is the C# version failing to compile?

Was it helpful?

Solution

VB is rather looser with ByRef parameters than C# is. For example, it allows you to pass properties by reference. C# doesn't allow this.

In a similar way, with Option Strict off, VB allows you to use an argument which is a subtype of the declared parameter. As a short but complete program, consider this:

Imports System

Public Class Test
    Public Shared Sub Main(args As String())
        Dim p As String = "Original"
        Foo(p)
        Console.WriteLine(p)
    End Sub

    Public Shared Sub Foo(ByRef p As Object)
        p = "Changed"
    End Sub
End Class

That works in VB, but the equivalent in C# wouldn't... and for good reason. It's dangerous. In this case, we're using a string variable and we happen to change p to refer to another string, but if we change the body of Foo to:

p = new Object()

Then we get an exception at execution time:

Unhandled Exception: System.InvalidCastException: Conversion from type 'Object' to type 'String' is not valid.

Basically ref is compile-time type-safe in C#, but ByRef isn't type-safe in VB with Option Strict off.

If you add:

Option Strict On

to the program in VB, however (or just change the defaults for your project) you should see the same problem in VB:

error BC32029: Option Strict On disallows narrowing from type 'Object' to type
'String' in copying the value of 'ByRef' parameter 'p' back to the matching
argument.

        Foo(p)
            ~

This suggests that you're currently coding without Option Strict... I'd recommend using it ASAP.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top