dotNET
dotNET

Reputation: 35410

Why List(Of T) doesn't have Count()?

Public Class MyList
    Inherits List(Of MyObject)

    Public ReadOnly Property SelectedCount() As Integer
        Get
            Return Me.Count(Function(obj) obj.IsSelected)
        End Get
    End Property
End Class

The above code causes a compile-time error. As you can see, I'm trying to use extension method Count(<predicate>). I guess the error is because there is a similarly-named property Count in List class itself too, hiding the extension member.

My questions here are:

  1. Do I need to explicitly cast my class to something else to access Count extension method? If so, exactly which class should it be in the above scenario?

  2. Why can't the compiler infer from the usage that I'm referring to a method and not a property?

  3. Does casting involve significant overhead considering that this is a heavily used method (may at times be called hundreds of times a second)?

  4. Is C# any better than VB.NET in this regard?

I'm using .NET 4.0 with VS2010 if that has something to do.

EDIT

Error message:

'Public ReadOnly Property Count As Integer' has no parameters and its return type cannot be indexed.

Upvotes: 8

Views: 1168

Answers (4)

Meta-Knight
Meta-Knight

Reputation: 17875

Use AsEnumerable for this purpose:

Public ReadOnly Property SelectedCount() As Integer
    Get
        Return Me.AsEnumerable.Count(Function(obj) obj.IsSelected)
    End Get
End Property

Upvotes: 5

Dan
Dan

Reputation: 9847

Call the method without the extension method syntax:

Public Class MyList
    Inherits List(Of MyObject)

    Public ReadOnly Property SelectedCount() As Integer
        Get
            Return Enumerable.Count(Me, Function(obj) obj.IsSelected)
        End Get
    End Property
End Class

Make sure you have added an import to System.Linq.

Upvotes: 6

MarcinJuraszek
MarcinJuraszek

Reputation: 125640

  1. You can cast Me to IEnumerable(Of MyObject):

    Return DirectCast(Me, IEnumerable(Of MyObject)).Count(Function(obj) obj.IsSelected)
    

    Or use Enumerable.Count() method directly:

    Return Enumerable.Count(Me, Function(obj) obj.IsSelected)
    

    Extension Methods are transformed by compiler into direct static (shared in VB) methods calls, so there is no difference.

  2. Have no idea, really.

  3. Casting to underlying type does not change the object itself, so there is no performance penalty (unless boxing is involved, what is not a case here).

  4. C# does not allow properties with parameters and it requires properties to be called without (), so yes, it's better in situations like this one.

    In VB.NET both Me.Count() and Me.Count refer to Count property of List(Of T). In C# this.Count would refer to property and this.Count() would refer the extension method (because of parentheses).

Upvotes: 5

TrueWill
TrueWill

Reputation: 25543

To answer #4, this works fine in C#:

public class MyObject { public bool IsSelected { get { return true; } } }

public class MyList : List<MyObject>
{
    public int SelectedCount
    {
        get { return this.Count(x => x.IsSelected); }
    }
}

Upvotes: 1

Related Questions