1

私は Linq to Objects を初めて使用し、匿名型とスコープの問題にぶつかりました。

たとえば、これは問題なく機能します。

    Public Sub CreateResults()
        results = From e In CustomerList
                  Join f In OrderList On CustomerList.ID Equals OrderList.ID
                  Select New With {e.FirstName, e.LastName, f.OrderID}

        For Each r in results
            Console.Writeline(r.FirstName, r.LastName, r.OrderID)
        Next t
    End Sub

ただし、これは次のことを行いません。

Public Class Foo

    Private _linqResults 

    Public Sub CreateResults()
        _linqResults = From e In CustomerList
                       Join f In OrderList On CustomerList.ID Equals OrderList.ID
                       Select New With {e.FirstName, e.LastName, f.OrderID}
    End Sub

    Public Sub PrintResults()
        For Each r in _linqResults
            Console.Writeline(r.FirstName, r.LastName, r.OrderID)
        Next t
    End Sub

End Class

私はSOや他の場所を調べて、これに対する簡単な解決策を見つけようとしていますが、運が悪いです。Linq クエリを含むメソッドのスコープ外の匿名型のフィールドにアクセスする方法はありますか? 何かのようなもの:

Console.Writeline(r("FirstName").ToString, r("LastName").ToString)

理想的ではありませんが、許容されます。

私は本当に、動的クエリと思われるものを処理するために、追加のクラス/構造/DTO の作成を開始したくありません。

4

2 に答える 2

2

思い通りに型を推測することはできません。ただし、いくつかの選択肢があります。

  1. 追加のクラスを作成します(これは望ましくありません)

  2. クラスのスタイルを変更して、CreateResults と PrintResults が行ったのと同じメソッドになるようにします。しかし、あなたにはそうしない正当な理由があります。

  3. 動的型を使用します (VB にはあると思いますが、確かにはわかりません。私は C# の人間です)。次に、例のように、必要なプロパティに簡単にアクセスします。これは明らかに静的型付けほど高速ではありません。
  4. それを行うためのハックがあります (少なくとも C# では)。しかし、それはきれいではありません。Linq の使用中に匿名型を返す方法を参照してください。
  5. カスタム クラスを使用する代わりに、タプル クラスを使用できます。System.Tuple を作成し、そこにデータを保存します。彼らは.Net 4に入ったと思います。

最終的には、そうしない正当な理由がない限り、カスタム クラスが最適な方法だと思います。私もあなたが望むのと同じことをする方法が欲しいのですが、カスタムクラスは新しい構文で数行で記述できます。

編集:いくつかのポイントを追加し、少し変更しました

要求に応じて C# での動的な例

class Foo
{
    private dynamic _linqResults;

    public void CreateResults()
    {
        var someData = Enumerable.Range(1, 10);

        _linqResults = from i in someData
                       select new
                       {
                           Number = i
                       };
    }

    public void PrintResults()
    {
        foreach (var i in _linqResults)
            Console.WriteLine(i.Number);
    }
}

ご覧のとおり、必要な構文とほぼ同じです。少し遅いダイナミックを使用するだけですが、データグリッドとcsvで何らかのダイナミック/リフレクションをすでに使用しているか、使用する予定のようです。原因は、使用する DataGrid と CSV (独自の?) によって異なります。

別の回答で述べたように、コンパイラは型を推測できず、IntelliSense は PrintResults のガイドにはなりません。

少し更新 VB には同様の構文があり、ここで適切なウォークスルーを見つけることができます: http://blogs.msdn.com/b/vbteam/archive/2008/12/17/walkthrough-dynamic-programming-in-visual -basic-10-0-and-c-4-0-lisa-feigenbaum.aspx

于 2010-07-07T20:55:30.870 に答える
1

これが取引です。

匿名型を作成しています。コンパイラは、作成されたスコープ内の匿名型についてのみ「認識」します。

2 番目の例では、その匿名型をその作成の範囲外に格納しようとしています。これを行うことはできますが、型が匿名であるため、リフレクションを介する場合を除き、コンパイラによって生成されたプロパティにアクセスできなくなります。

簡単に言うと、linq クエリの結果を、それが作成されたスコープの外に格納したい場合は、それらの結果を保持する型を作成する必要があります。

于 2010-07-07T20:56:33.927 に答える