Question

What is the proper way to create a variable that will house a list of anonymous objects that are generated through a LINQ query while keeping the variable declaration outside of a try/catch and the assignment being handled inside of a try/catch?

At the moment I'm declaring the variable as IEnumberable<object>, but this causes some issues down the road when I'm trying to use it later...

i.e.

var variableDeclaration;
try{
    ...
    assignment
    ...
}catch...

EDIT:

If it's relevant (don't think it is) the list of objects is being returned as a Json result from an MVC3 action. I'm trying to reduce the time that some using statements are open with the DB as I'm having some performance issues that I'm trying to clear up a bit. In doing some of my testing I came across this issue and can't seem to find info on it.

EDIT 2:

If I could request the avoidance of focusing on LINQ. While LINQ is used the question is more specific to the scoping issues associated with Anonymous objects. Not the fact that LINQ is used (in this case) to generate them.

Also, a couple of answers have mentioned the use of dynamic while this will compile it doesn't allow for the usages that I'm needing later on the method. If what I'm wanting to do isn't possible then at the moment the answer appears to be to create a new class with the definition that I'm needing and to use that.

Was it helpful?

Solution

It's possible to get around this by creating a generic Cast method as outlined by Jon Skeet here. It will work and give you the intellisense you want. But, at this point, what's wrong with creating a custom type for your linq method?

public class MyClass
{
    public int MyInt { get; set; }
}

IEnumerable<MyClass> myClass = 
    //Some Linq query that returns a collection of MyClass

OTHER TIPS

Well, if you're using LINQ, the query is not evaluated unless materialized...

So, you might be able to:

var myQuery = //blah
try
{
    myQuery = myQuery.ToList();  //or other materializing call
}
catch
{
}

Could you perhaps get away with using dynamic ??

     dynamic variableDeclaration;
     try
     {
         variableDeclaration = SomeList.Where(This => This == That);
     }
     catch { }

Not sure what this will affect further in your code block, but just a thought :)

If you are declaring the variable ahead of using it like a try/catch you can't use [var] as it is intendend. Instead you have to type the the variable.

var x = 0;
try{
   x = SomethingReturningAnInt();
}

or

int x;
try{
   x = SomethingReturningAnInt();
}

However in your case you don't really "know" what the method returns

var x = ...;
try{
   x = Something();
}
catch{}

won't work

Option you have when you don't know the type in advance is use of dynamic:

dynamic x;
try{
   x = Something();
}
catch{}

(But that feels like going back to VB4)

Another cheat: you can define variable locally (similarly to Jon's hack in Dave Zych answer) and than use it inside try/catch. As long as you can create the same anonymous item type before try-catch you are OK (as anonymous types wit the same field names and types are considered the same):

var myAnonymouslyType = Enumerable.Repeat(
    new {Field1 = (int)1, Field2 = (string)"fake"}, 0);

try 
{ 
   myAnonymouslyType = ...(item => 
     new {Field1 = item.Id, Field2=item.Text})...
}
...

This is safer option than covered in Jon's casting of anonymous types between functions because compiler will immediately find errors if types don't match.

Note: I'd vote for non-anonymous type if you have to go this way...

Note 2: depending on your actual need consider simply returning data from inside try/catch and having second return of default information outside.

This has vexed me for a while. In the end I've build some Generic helper methods where I can pass in the code that generates the anonymous objects, and the catch code as lamdas as follows

public static class TryCatch
{
    public static T Expression<T>(Func<T> lamda, Action<Exception> onException)
    {
        try
        {
            return lamda();
        }
        catch(Exception e)
        {
            onException(e);
            return default(T);
        }            
    }

}

//and example

Exception throwexception = null;
        var results = TryCatch.Expression(
            //TRY
            () => 
                {
                    //simulate exception happening sometimes.
                    if (new Random().Next(3) == 2)
                    {
                        throw new Exception("test this");
                    }
                    //return an anonymous object
                    return new { a = 1, b = 2 };
                } ,
            //CATCH
            (e) => { throwexception = e;                         
                     //retrow if you wish
                     //throw e;
                   }
            );

https://gist.github.com/klumsy/6287279

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top