2016-08-05 15 views
0

最近特定のObjectプロパティに基づいてリストから個別の値を取得する方法が必要でした(この場合、aタイムスタンプはDateTimeの形式です)。ちょっとしたグーグルの後、私はSOスレッドに出くわしました。そこには、DistinctBy()という拡張機能があり、コレクションを繰り返し処理し、異なるプロパティ値を持つアイテムを返します。コードは以下の通りです。".DistinctBy()はすべてのコードパスで値を返しません"警告

<Extension()> _ 
    Public Function DistinctBy(Of TSource, TKey)(source As IEnumerable(Of TSource), keySelector As Func(Of TSource, TKey)) As IEnumerable(Of TSource) 
     Dim seenKeys As New HashSet(Of TKey)() 
     For Each element As TSource In source 
      If seenKeys.Add(keySelector(element)) Then 
       Return CType(element, Global.System.Collections.Generic.IEnumerable(Of TSource)) 
      End If 
     Next 
    End Function 

コードはもともとC#で作成されていましたが、コードコンバータを使用してVisual Basicに変更しました。つまり、VS2013では、関数がすべてのコードパスで値を返さないという警告が表示されています。私は、エラーが何を意味しているのか、また通常の状況ではどのように修正するのかを認識しています。しかし、これを検討する方法がわからないのは、IEnumerableオブジェクトを返す関数です。私はIEnumerable関数の仕組みに慣れていませんし、関数が動作するかどうかもわかりません!

誰でもこの状況を明確にすることはできますか?

+0

'と元のコードに含まれるステート・マシンyieldキーワードを使用します。一方、VB.NETもそれをサポートしています。 –

+0

自動コードコンバータは、信頼性の低いものです。メソッドは何を*返すべきですか?それは何をするためのものか*? 'source'が空であるか、' If'条件が決して満たされない場合、それは何を返すべきですか? – David

+0

コンバータによって行われる典型的なハックジョブのように見えます。 VB.NETはイテレータをサポートするために使用されていなかったため、何か別のものを考え出す必要がありました。ロジックはかなり壊れているように見えますが、元のC#コードを投稿する方が良いでしょう。 –

答えて

1

original code含まれるステート・マシンになるので、それはまたあなたのためのVB.Netで利用可能であるべきです。その間にVB.NET supports it。 LINQの有名な遅延実行です。

<Extension()> _ 
Public Iterator Function DistinctBy(Of TSource, TKey)(source As IEnumerable(Of TSource), keySelector As Func(Of TSource, TKey)) As IEnumerable(Of TSource) 
    Dim seenKeys As New HashSet(Of TKey)() 
    For Each element As TSource In source 
     If seenKeys.Add(keySelector(element)) Then 
      Yield element 
     End If 
    Next 
End Function 

あなたがYieldを知らないの.NETバージョンをサポートしなければならなかった場合は、一度にすべてのアイテムを返します。このアプローチを使用することができますが:

<Extension()> _ 
Public Function DistinctBy(Of TSource, TKey)(source As IEnumerable(Of TSource), keySelector As Func(Of TSource, TKey)) As IEnumerable(Of TSource) 
    Dim seenKeys As New HashSet(Of TKey)() 
    Dim list = new List(Of TSource) 
    For Each element As TSource In source 
     If seenKeys.Add(keySelector(element)) 
      list.Add(element) 
     End If 
    Next 
    return list 
End Function 
+0

2番目のケースでは、遅延実行が失われます – Sehnsucht

+0

それは言及されている –

+0

'Yield'を使うために追加する必要がある特定のライブラリはありますか?私が尋ねる唯一の理由は、すぐに使えないということです.VSは、 "収量は宣言されていません"と言っています。 – Fredulom

1

初期C#コードで(おそらく)イテレータメソッド(yieldを使用)でした。
正しい変換がyieldキーワードと

<Extension()> _ 
Public Iterator Function DistinctBy(Of TSource, TKey)(source As IEnumerable(Of TSource), keySelector As Func(Of TSource, TKey)) As IEnumerable(Of TSource) 
    Dim seenKeys As New HashSet(Of TKey)() 
    For Each element As TSource In source 
     If seenKeys.Add(keySelector(element)) Then 
      Yield element 
     End If 
    Next 
End Function 
関連する問題