10

Visual Basic からEnumerable.Count()拡張メソッドを使用しようとすると、次のコードでコンパイル エラーが発生します。

Imports System.Linq

Module Module1

    Sub Main()
        Dim l As New List(Of Foo) From {New Foo("a"), New Foo("b"), New Foo("a")}

        Dim i As Integer = l.Count(Function(foo) foo.Bar = "a")

        Console.WriteLine(i)
        Console.ReadLine()
    End Sub

    Class Foo

        Sub New(ByVal bar As String)
            Me.Bar = bar
        End Sub

        Public Property Bar As String
    End Class
End Module

生成されるエラーは次のとおりです。

'Public ReadOnly Property Count As Integer' にはパラメーターがなく、その戻り値の型にインデックスを付けることができません。

私は .NET 4.0 をターゲットにしているので、拡張メソッドをサポートする必要があります。C# の同等のコードが拡張メソッドを正しく推論することも注目に値します...

引数として渡した述語を指定すると、コンパイラが Enumerable.Count の使用を推測できないのはなぜですか? また、List の Count プロパティの代わりに拡張メソッドを使用するにはどうすればよいですか?

4

4 に答える 4

2

オプションとしてオーバーロードを取得しない理由はわかりませんが、コンパイラがプロパティIEnumerable(Of Foo)を許可しなくなる時点でリストをキャストできるはずです。List(Of Foo).Count

CType(l, IEnumerable(Of Foo)).Count(Function(foo) foo.Bar = "a")
于 2013-04-12T02:54:03.917 に答える
2

この場合、C# ができることを VB ができない理由についての質問に答えるには...

VB では()、名前の後ろにあるプロパティにアクセスでき()ます。. また、インデクサーは、C# にある角かっこの代わりに丸かっこを使用します。これらは、プログラミングを容易にするために設計された VB の優れた機能の例ですが、実際には、より曖昧で理解しにくく、バグが発生しやすいコードになります。

したがって、この特定のケースでは、VB は、Count にアクセスしていることを認識し、Count 関数への引数ではなく、Count プロパティへのインデクサーであると見なします。

C# は丸かっこを見て、インデクサーにアクセスしていないことを認識します。関数を呼び出す必要があるため、関数を探します。

もちろん、C# にもあいまいさの余地があります。たとえば、デリゲート型を返す拡張メソッドと同じ名前のプロパティは、拡張メソッドよりも優先して呼び出されます...

public Action Count { get; set; }

あぁ…幸せな日々。

IEnumerable.Count() 関数を呼び出す方法については、キャスト (できればDirectCast()) または拡張メソッドを直接実行する方がEnumerable.Count(...)、count を呼び出すためにまったく新しい配列を作成するよりもはるかに優れています...!

于 2013-11-11T18:36:44.067 に答える