匿名类型范围问题

时间:2013-01-28 01:52:54

标签: c# scope anonymous-objects

创建变量的正确方法是什么,该变量将包含通过LINQ query生成的匿名对象列表,同时将变量声明保留在try/catch之外,并且在内部处理赋值一个try/catch

目前我正在将变量声明为IEnumberable<object>,但是当我稍后尝试使用它时,这会导致一些问题......

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

修改

如果它是相关的(不要认为是),则对象列表将作为MVC3动作的Json结果返回。我正在尝试减少一些using语句对数据库打开的时间,因为我遇到了一些性能问题,我正试图清理一下。在进行一些测试时,我遇到了这个问题,似乎无法找到相关信息。

编辑2:

如果我可以请求避免关注LINQ。使用LINQ时,问题更具体于与Anonymous对象相关的范围问题。不是使用LINQ(在这种情况下)生成它们的事实。

另外,有几个答案提到dynamic的使用,而这将编译它不允许稍后我需要的方法使用。如果我想要做的事情是不可能的,那么目前答案似乎是创建一个新的class,其中包含我需要的定义并使用它。

6 个答案:

答案 0 :(得分:4)

好吧,如果你正在使用LINQ,除非实现了......否则不会评估查询...

所以,你可以:

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

答案 1 :(得分:4)

通过创建Jon Skeet here概述的通用Cast方法,可以解决这个问题。它会工作,并给你你想要的intellisense。但是,在这一点上,为linq方法创建自定义类型有什么问题?

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

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

答案 2 :(得分:1)

你是否可以使用dynamic ??

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

不确定这会对你的代码块产生什么影响,但只是想一想:)

答案 3 :(得分:1)

如果你在使用它之前声明变量就像try / catch那样你不能使用[var],因为它是意图。相反,你必须输入变量。

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

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

但是在你的情况下,你并不真正“知道”该方法返回的内容

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

不起作用

当您事先不知道类型时使用动态的选项:

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

(但感觉就像回到VB4)

答案 4 :(得分:1)

另一个作弊:你可以在本地定义变量(类似于Jon在Dave Zych中的黑客回答)而不是在try / catch中使用它。只要你可以在try-catch之前创建相同的匿名项类型就可以了(因为匿名类型具有相同的字段名称和类型被认为是相同的):

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

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

这比Jon's casting of anonymous types between functions中提到的更安全,因为如果类型不匹配,编译器会立即发现错误。

注意:如果你必须采用这种方式,我会投票给非匿名类型......

注意2:根据您的实际需要,考虑简单地从try / catch内部返回数据并在第二次返回默认信息。

答案 5 :(得分:1)

这让我烦恼了一会儿。最后,我构建了一些Generic助手方法,我可以传入生成匿名对象的代码,并将catch代码作为lamdas传递如下

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