EvilDr
EvilDr

Reputation: 9610

Option Strict causing compiling error within LINQ statement (implicit conversion 'Object' to 'Control')

We're currently converting a VB project to C#, and starting by enabling Option Strict. When enabled, the following line generates an error:

Dim visiblePanelCount As Integer = (From c As Control In pnl_AdminPageLinks.Controls 
                                     Where TypeOf (c) Is Panel AndAlso c.Visible 
                                     Select c).Count()

The red underline is on As Control with the error:

BC30512 Option Strict On disallows implicit conversions from 'Object' to 'Control'

I understand what the error means, but cannot understand where the type of Object is being created (as I believe that .Controls is a collection of type Control).

A second example which makes even less sense to me is "Object to DataRow" same error under As DataRow in this line:

Return (From dr As DataRow In MyDataTable.Rows ' error on As DataRow
        Select New MyClass() With {
            .Id = Convert.ToInt32(dr.Item("Id")),
            .UserId = Convert.ToInt32(dr.Item("UserId"))
        }).ToList()

I convert the code to C# which generated the same logic, so don't understand VB.Net's underlying problem.

Upvotes: 1

Views: 590

Answers (1)

jmcilhinney
jmcilhinney

Reputation: 54477

Remember that LINQ is based on the generic IEnumerable(Of T) interface and that Controls collection, despite containing only controls, does not implement IEnumerable(Of Control). It only implements IEnumerable so, when it is enumerated, it provides an Object reference only. The way to go from IEnumerable to IEnumerable(Of T) is with the Cast(Of T) method:

Dim visiblePanelCount = (From c In pnl_AdminPageLinks.Controls.Cast(Of Control)()
                         Where TypeOf (c) Is Panel AndAlso c.Visible 
                         Select c).Count()

You can do away with the type check by calling OfType(Of T) too, which also moots the Cast(Of T) call:

Dim visiblePanelCount = (From c In pnl_AdminPageLinks.Controls.OfType(Of Panel)()
                         Where c.Visible 
                         Select c).Count()

You can also omit the Select clause in VB if you are simply selecting the original query item:

Dim visiblePanelCount = (From c In pnl_AdminPageLinks.Controls.OfType(Of Panel)()
                         Where c.Visible).Count()

Given that the Count method will filter as well, you can simplify that query even further:

Dim visiblePanelCount = pnl_AdminPageLinks.Controls.OfType(Of Panel)().Count(Function(p) p.Visible)

Upvotes: 4

Related Questions