Как вы можете предварительно определить переменную, которая будет содержать анонимный тип? - PullRequest
3 голосов
/ 09 марта 2011

В приведенном ниже примере упрощенный я хочу определить result до его получения.Приведенные ниже запросы linq возвращают списки анонимных типов.result выйдет из запросов linq как IEnumerable <'a>, но я не могу определить его таким образом в верхней части метода.Возможно ли то, что я пытаюсь сделать (в .NET 4)?

            bool large = true;
            var result = new IEnumerable();   //This is wrong

            List<int> numbers = new int[]{1,2,3,4,5,6,7,8,9,10}.ToList<int>();

            if (large)
            {
                result = from n in numbers
                             where n > 5
                             select new
                             {
                                 value = n
                             };
            }
            else
            {
                result = from n in numbers
                             where n < 5
                             select new
                             {
                                 value = n
                             };
            }

            foreach (var num in result)
            {
                Console.WriteLine(num.value);
            }

РЕДАКТИРОВАТЬ: Для ясности я знаю, что мне не нужны анонимные типы в примере выше.Это просто для иллюстрации моего вопроса на небольшом простом примере.

Ответы [ 5 ]

3 голосов
/ 09 марта 2011

Анонимные типы могут быть объявлены только с var. Хорошо, что анонимные типы с одинаковыми свойствами будут одинаковыми. Если он вам действительно нужен (в этом примере он вам не нужен), вы можете написать:

var result = Enumerable.Repeat(new {value = 0}, 0); // stub value which will give needed type
if (...)
{
    result = ...;
}
else
{
    result = ...;
}

P.S .: это было возможно даже в предыдущей версии .Net (ниже 4.0)

1 голос
/ 09 марта 2011

Мне нравится ответ Snowbear, если у вас на самом деле есть , чтобы сделать это ... но лично я бы по крайней мере попытался , чтобы избежать попадания в эту ситуацию.Например, даже сохраняя анонимных типов, я бы изменил ваш исходный код на:

bool large = true;
var result = new IEnumerable();   //This is wrong

List<int> numbers = new int[]{1,2,3,4,5,6,7,8,9,10}.ToList<int>();

Func<int, bool> predicate = large ? new Func<int, bool>(x => x > 5)
                                  : x => x < 5;
var result = numbers.Where(predicate)
                    .Select(x => new { value = x });

foreach (var num in result)
{
    Console.WriteLine(num.value);
}

Обратите внимание, как это убрало дублирование - понятно, что only вещь, на которую влияет large, это предикат.

Я считаю, что код становится более понятным, если переменным присваивается только одно значение, в идеале в точке объявления.

Очевидно, это не такЭто всегда выполнимо, но стоит иметь в виду, где это возможно.Там, где это не возможно, ответ Snowbear хорош и гарантированно сработает.

1 голос
/ 09 марта 2011

Вы можете сделать его IEnumerable и просто выбрать «n» в своих запросах, а не создавать анонимный тип. EG:

IEnumerable<int> result = null;

result = from n in numbers
         where n > 5
         select n;

Если то, что вы на самом деле делаете , требует анонимного типа, тогда - поскольку вы используете C # 4 - вы можете объявить IEnumerable<dynamic> result, и весь остальной код будет работать.

0 голосов
/ 09 марта 2011

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

bool large = true;
List<int> numbers = new int[]{1,2,3,4,5,6,7,8,9,10}.ToList<int>();

IEnumerable<int> query;
if (large) {
    query = query.Where(n => n > 5);
} else {
    query = query.Where(n => n < 5);
}

var result = query.Select(n => new { Value = n });

foreach (var num in result) {
    Console.WriteLine(num.Value);
}
0 голосов
/ 09 марта 2011

Вы должны определить тип заранее. Э.Г.

public class TheNumber
{
  public int Number { get; set; }
}

....

IEnumerable<TheNumber> result;
result = numbers.Where(n => n > 5).Select(n => new TheNumber() { Number = n });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...