如何预先定义一个包含匿名类型的变量?

时间:2011-03-09 17:39:53

标签: linq c#-4.0

在下面的简化示例中,我想在合并之前定义result。下面的linq查询返回匿名类型的列表。 result将作为IEnumerable<'a>来自linq查询。但我无法在方法的顶部以这种方式定义它。我正在尝试做什么(在.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 个答案:

答案 0 :(得分:3)

只能使用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 :(得分:1)

您可以将其设为IEnumerable,只需在查询中选择“n”,而不是创建匿名类型。 EG:

IEnumerable<int> result = null;

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

如果您实际在做什么需要匿名类型,那么 - 因为您正在使用C#4 - 您可以声明IEnumerable<dynamic> result,其余代码将工作

答案 2 :(得分:1)

如果你真的 这样做,我喜欢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);
}

请注意这是如何消除重复的 - 更明确large影响的事物是谓词。

我发现,如果变量只被分配了一个值,理想情况下是在声明点,那么代码最终会更清晰。

显然,这并不总是可行的,但在可能的情况下,值得记住。在可能的地方,Snowbear的答案很好并保证可以正常工作。

答案 3 :(得分:0)

您必须事先定义类型。 E.g。

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

...

IEnumerable<TheNumber> result;
result = numbers.Where(n => n > 5).Select(n => new TheNumber() { Number = n });

答案 4 :(得分:0)

如果在创建匿名类型后不需要任何条件部分,则可以部分构建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);
}