I haven't noticed this behaviour yet, maybe because i prefer query syntax in VB.NET and split the query and the execution-methods into different statements.
If i try to compile following simple query:
Dim wordList As List(Of String) = New List(Of String)
Dim longWords As Int32 = wordList.Count(Function(word) word.Length > 100)
The compiler doesn't like this because he expects no arguments for List.Count
:
"Public Readonly Property Count As Integer" has no parameters and its return type cannot be indexed.
If i declare it as IEnumerable(Of String)
it works as expected:
Dim wordSeq As IEnumerable(Of String) = New List(Of String)
Dim longWords As Int32 = wordSeq.Count(Function(word) word.Length > 100)
Why is that so? What prevents the compiler from using the Enumerable
extension method Count
instead of the ICollection.Count
property. Note that i've added Imports System.Linq
and both Option Strict
and Option Infer
are On
. I'm using.NET 4.0 (Visual Studio 2010).
I'm confused because in C# this works without a problem:
List<String> wordList = new List<String>();
int longWordCount = wordList.Count(word => word.Length > 100);
It's by design, quote from MSDN:
The situation is simpler with properties: if an extension method has the same name as a property of the class it extends, the extension method is not visible and cannot be accessed.
In C#, only way to call a property is using property syntax (i.e) instance.PropertyName
where as in Vb.Net there are two options.
Dim list As List(Of String) = New List(Of String)()
Dim count = list.Count() //Method 1
Dim count2 = list.Count //Method 2
Assume you add a Count
extension method with no parameters, what does list.Count()
mean? It always gives priority to instance members so it points to Property.
Ok, What does list.Count(Function(s) s.StartsWith("a"))
means? In this case it mean the extension method?
There is no consistency in the language then, I guess designers deliberately avoided this feature for consistency.
If you cast to IEnumerable when you need the extension method, everything will be fine:
Dim longWords As Int32 = CType(wordList, IEnumerable(Of String)).Count(Function(word) word.Length > 100)
Or as dcastro mentioned in a comment:
Dim longWords As Int32 = wordList.AsEnumerable.Count(Function(word) word.Length > 100)
One of the primary purpose of the AsEnumerable
method is specifically to be used when the type of an IEnumerable
object has a member that takes precedence over one of the LINQ extension methods, so you should simply add in a call to AsEnumerable
before calling Count
, to remove the member conflict.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With