Линк к объектам и анонимным типам - PullRequest
1 голос
/ 08 июля 2010

Я новичок в 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 для обработки того, что должно быть динамическим запросом.

Ответы [ 2 ]

2 голосов
/ 08 июля 2010

Невозможно выводить типы так, как вы хотите. У вас есть несколько вариантов:

  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);
    }
}

Как вы, возможно, видите, это почти тот же синтаксис, что и вы. Он просто использует динамику, которая немного медленнее, но похоже, что вы уже используете или будете использовать какую-то динамику / отражение в datagrid и 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

1 голос
/ 08 июля 2010

Вот сделка.

Вы создаете анонимный тип. Компилятор только «знает» об анонимном типе в области его создания.

Во втором примере вы пытаетесь сохранить этот анонимный тип вне области его создания. Вы можете сделать это, но так как тип является анонимным, вы теряете возможность доступа к свойствам, сгенерированным компилятором, кроме как через отражение.

Короче говоря, если вы хотите сохранить результаты запроса linq вне создаваемой области, вы должны создать тип для хранения этих результатов.

...