トップ回答者
ListクラスでのLINQのCountメソッドがビルドエラー

質問
-
VB2013で
Listクラスで条件を満たす要素数を数えるのに、
predicateデリゲートを指定したLINQのCountメソッドを使いたいのですが、ListクラスのCountプロパティとみなされてビルドエラーになります。
Whereメソッドを経由させる以外の回避法はないものでしょうか?Module Module1 Sub Main() Dim wkList = Enumerable.Range(1, 10).ToList 'predicateデリゲートを使いたいけど、VBだとビルドが通らない 'Console.WriteLine(wkList.Count(Function(X) X >= 5)) 'これだと、ビルドが通るけど、Whereメソッドを経由させたくないなぁ Console.WriteLine(wkList.Where(Function(X) X >= 5).Count) End Sub End Module
回答
-
> 今のところちょっと謎ですね・・・
trapemiya さんが紹介された MSDN Forum のスレッドで、Matt Warren - MSFT さんが、
"VB compiler is matching the lists Count property instead of the Enumerable.Count() extension method and the Count property is blocking the visibility of the extension method's other signature."
Timothy Ng MSFT さんが、
"in VB, properties shadow methods (and thus, extension methods) by name."
と書いた説明、即ち VB.NET のコンパイラの問題ということで自分的には納得しているのですが。(公式文書ではないといわれるかもしれませんが)
質問者さんのコードで wkList は List(Of Int32) 型、List(Of Int32) 型には Count プロパティが実装されている、なので VB.NET で wkList.Count では拡張メソッドの Count が shadow される・・・ということのようです。
回避策は、
(1) Hongliang さんが書いたように明示的に拡張メソッドの Count を使用したコードにする。
(2) 私がレスしたように ToList を止める(Count プロパティを実装してない IEnumerable(Of Int32) 型に適用する)。
のいずれかしかなさそうです。
- 回答としてマーク tokugawatokugawa 2015年12月9日 6:34
すべての返信
-
> ListクラスのCountプロパティとみなされてビルドエラーになります。
MSDN ライブラリに書いてあったように "source の型が ICollection(Of T) を実装している場合は、その実装を使用して要素数を取得します。それ以外の場合は、このメソッドが数を判断します。" ということだからでは?
【追伸】
ToList を止めれば通るはずです。
Dim e As IEnumerable(Of Int32) = Enumerable.Range(1, 10) Dim x As List(Of Int32) = e.ToList Console.WriteLine(e.Count(Function(n) n >= 5)) 'Public ReadOnly Property Count As Integer' には引数がないため、戻り値の型をインデックス化できません。 'Console.WriteLine(x.Count(Function(n) n >= 5))
C# ならどちらも OK。
IEnumerable<int> e = Enumerable.Range(1, 10); List<int> x = e.ToList(); Console.WriteLine(e.Count(n => n >= 5)); Console.WriteLine(x.Count(n => n >= 5));
- 編集済み SurferOnWww 2015年12月9日 3:29 追伸追加
-
C#では全く問題ないので、不思議に思い調べてみました。
Strange Behavior of VB 9.0 Count() Operator with Predicate t
https://social.msdn.microsoft.com/Forums/en-US/34a66c1f-81d4-4f6f-bab5-2a0be64db1ec/strange-behavior-of-vb-90-count-operator-with-predicate?forum=linqprojectgeneralLinq count?
http://www.vbdotnetforums.com/linq/48359-linq-count.html上記のページでは結局解決していませんし、上記のページで紹介されているconnectのページも今は存在しないようです。
今のところちょっと謎ですね・・・
★良い回答には回答済みマークを付けよう! MVP - .NET http://d.hatena.ne.jp/trapemiya/
- 編集済み trapemiyaModerator 2015年12月9日 4:31 リンク先にうまく飛ばないので再設定
-
以下の説明によると、VBでは()を使ってプロパティにアクセスできるので(配列プロパティですね)、プロパティとメソッドとの区別ができないんだとか・・・。というわけで、言語仕様上の限界のように思えます。
How do I specify Enumerable.Count() instead of List.Count?
http://stackoverflow.com/questions/15961308/how-do-i-specify-enumerable-count-instead-of-list-count★良い回答には回答済みマークを付けよう! MVP - .NET http://d.hatena.ne.jp/trapemiya/
-
> 今のところちょっと謎ですね・・・
trapemiya さんが紹介された MSDN Forum のスレッドで、Matt Warren - MSFT さんが、
"VB compiler is matching the lists Count property instead of the Enumerable.Count() extension method and the Count property is blocking the visibility of the extension method's other signature."
Timothy Ng MSFT さんが、
"in VB, properties shadow methods (and thus, extension methods) by name."
と書いた説明、即ち VB.NET のコンパイラの問題ということで自分的には納得しているのですが。(公式文書ではないといわれるかもしれませんが)
質問者さんのコードで wkList は List(Of Int32) 型、List(Of Int32) 型には Count プロパティが実装されている、なので VB.NET で wkList.Count では拡張メソッドの Count が shadow される・・・ということのようです。
回避策は、
(1) Hongliang さんが書いたように明示的に拡張メソッドの Count を使用したコードにする。
(2) 私がレスしたように ToList を止める(Count プロパティを実装してない IEnumerable(Of Int32) 型に適用する)。
のいずれかしかなさそうです。
- 回答としてマーク tokugawatokugawa 2015年12月9日 6:34