Ben Junior
Ben Junior

Reputation: 2589

Declaration of list of anonymous types

I don't know if the question is properly formatted but what I'm trying to do is to create the var reservations outside the using loop but don't know how to initialize it.

This code works :

using (MainContextDB db = new MainContextDB())
{
    var reservations = (from c in db.Reservations select new { c.CustAcctNo, c.ReservNo, c.ReservStatus }).ToList();
}

Any attempt to declare the var outside the loop will trigger an error:

Cannot convert List to List

I've tried:

var reservations = new List<dynamic>();
var reservations = new List<object>();

This code works, but requires to retrieve all columns, which is not what I want:

List<Reservation> reservations = new List<Reservation>();
using (MainContextDB db = new MainContextDB())
{
    reservations = db.Reservations.ToList();
}

Upvotes: 2

Views: 717

Answers (3)

Kirill Shlenskiy
Kirill Shlenskiy

Reputation: 9587

Note: I would use none of the below approaches in performance-sensitive code.

Having said that, I am seeing a very simple solution here which can also be applied when you're dealing with types other than List<T>. A bit of type inference gets the job done:

private T InvokeAndReturn<T>(Func<T> func)
{
    return func();
}

Usage:

// reservations is List<'a>.
var reservations = this.InvokeAndReturn(() =>
{
    using (var db = new MainContextDB())
    {
        return db.Reservations
            .Select(c => new { c.CustAcctNo, c.ReservNo, c.ReservStatus })
            .ToList();
    }
});

Fresh edit

Just had to use this in my own code and opted for an IDisposable-aware alternative instead:

TReturn Using<TDisposable, TReturn>(TDisposable disposable, Func<TDisposable, TReturn> func)
    where TDisposable : IDisposable
{
    try
    {
        return func(disposable);
    }
    finally
    {
        if (disposable != null)
        {
            disposable.Dispose();
        }
    }
}

Usage:

var reservations = Using(new MainContextDB(), db =>
{
    return db.Reservations
        .Select(c => new { c.CustAcctNo, c.ReservNo, c.ReservStatus })
        .ToList();
});

Or an even shorter version

var reservations = Using(new MainContextDB(), db =>
    db.Reservations
        .Select(c => new { c.CustAcctNo, c.ReservNo, c.ReservStatus })
        .ToList()
);

Upvotes: 0

Enigmativity
Enigmativity

Reputation: 117019

You could do it this way:

var reservations = new []
{
    new { CustAcctNo = "", ReservNo = "", ReservStatus = "" }
}.ToList();

using (MainContextDB db = new MainContextDB())
{
    reservations = (
        from c in db.Reservations
        select new
        {
            c.CustAcctNo, c.ReservNo, c.ReservStatus
        }).ToList();
}

You just have to make sure you match the types on the members of your anonymous class.


The other option is to add a reference to the Microsoft Reactive Framework Team's "Interactive Extensions". They have a nice Using method for enmerables that lets you do this:

var reservations = 
    EnumerableEx
        .Using(
            () => new MainContextDB(),
            db =>
                from c in db.Reservations
                select new
                {
                    c.CustAcctNo, c.ReservNo, c.ReservStatus
                })
        .ToList();

Upvotes: 2

Kelly Robins
Kelly Robins

Reputation: 7288

Ok that ended up being a really interesting question-

I know that anonymous types aren't supposed to leave the method context, hadn't really thought about them leaving scope though...

I see a few possible options...

  • Do something hackey - Two anon types with the same signature share the same type, so you could coerce it into accepting a prototype and go from there. (converting into a list is difficult but doable in generics... see the link posted by simo)

  • Move the operations into your using context which I know isn't ideal

  • Manually dispose the context

  • Handle the items as dynamic

  • You could substitute a custom type or a tuple for the anonymous type

Hope that helps, I'm somewhat suprised there isn't a straightforward way to do this if you are remaining inside a method scope.

Upvotes: 1

Related Questions