HitLikeAHammer
HitLikeAHammer

Reputation: 2695

How can you pre-define a variable that will contain an anonymous type?

In the simplified example below I want to define result before it is assinged. The linq queries below return lists of anonymous types. result will come out of the linq queries as an IEnumerable<'a> but I can't define it that way at the top of the method. Is what I am trying to do possible (in .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);
            }

EDIT: To be clear I know that I do not need anonymous types in the example above. It is just to illustrate my question with a small, simple example.

Upvotes: 3

Views: 802

Answers (5)

mgronber
mgronber

Reputation: 3419

You could build the LINQ query in parts if you do not need any conditional parts after creating the anonymous type. Otherwise it is probably wiser to define a new struct/class to be used in place of anonymous type.

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

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1502216

I like Snowbear's answer here if you actually have to do this... but personally I would at least try to avoid getting into this situation. For example, even keeping the anonymous types, I would change your original code to:

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

Note how this has removed duplication - it's clearer that the only thing that large affects is the predicate.

I find that code ends up being clearer if variables are only assigned a single value, ideally at the point of declaration.

Obviously this isn't always feasible, but it's worth bearing in mind where possible. Where it's not possible, Snowbear's answer is fine and guaranteed to work.

Upvotes: 1

Snowbear
Snowbear

Reputation: 17274

Anonymous types can be declared only with var. The good thing is that anonymous types with same properties will be the same types. If you really need it (in this sample you don't need it) then you can write:

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

P.S.: this was possible even in previous .Net version (lower than 4.0)

Upvotes: 3

Jaben
Jaben

Reputation: 426

You have to define the type beforehand. 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 });

Upvotes: 0

Chris Wenham
Chris Wenham

Reputation: 24017

You can make it an IEnumerable and just select 'n' in your queries, rather than create an anonymous type. EG:

IEnumerable<int> result = null;

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

If what you're actually doing requires an anonymous type, then--since you're using C# 4--you can declare IEnumerable<dynamic> result, and the rest of your code will work.

Upvotes: 1

Related Questions