【问题标题】:Anonymous type scoping issue匿名类型范围问题
【发布时间】:2013-01-11 08:12:20
【问题描述】:

创建一个变量的正确方法是什么?

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

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

编辑:

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

编辑 2:

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

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

【问题讨论】:

  • 站在浴室里关灯,对着镜子小声说“Jon Skeet”10次。
  • @Doc nice...(臭气熏天的最小字符数导致了这个括号声明)
  • 如果您知道匿名类型列表的结构,但您还没有准备好填写它,您可以预先生成该类型的空列表。请参阅this post 了解更多信息。

标签: c# scope anonymous-objects


【解决方案1】:

可以通过创建由 Jon Skeet here 概述的通用 Cast 方法来解决此问题。它会起作用并为您提供所需的智能感知。但是,此时为您的 linq 方法创建自定义类型有什么问题?

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

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

【讨论】:

  • 我实际上已经考虑过这一点,但由于对象被严格用于返回 Json,我希望避免这种情况,因为那里没有不必要的代码(如果这是唯一的选择,那么它可能变得有必要)。匿名对象严格返回数据库中存在的实际对象的数据子集...如此处所述msdn.microsoft.com/en-us/library/vstudio/bb384105.aspx
  • @spender 我实际上有 R# 并且不知道如何执行此操作。介意发帖吗?
  • @Jared,在你新建匿名类型的地方,在 new{ 和“refactor-this”(ctrl-shift-r)之间放置插入符号,然后选择“用命名替换匿名类型类”
  • @DaveZych 正在等待除动态之外的其他方法,看起来这是我将采用的解决方案。我暂时实施了这一点,因为它确实解决了我的问题并且是我所知道的(只是希望避免)。如果没有其他内容弹出,我可能会再给这个答案,然后选择作为答案。谢谢!
【解决方案2】:

好吧,如果您使用的是 LINQ,除非具体化,否则不会评估查询...

所以,你也许可以:

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

【讨论】:

  • LINQ 查询是针对我们的 DB 对象...自定义的,所以目前我很遗憾不相信这是一个选项。
【解决方案3】:

你能不能使用dynamic ??

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

不确定这会进一步影响您的代码块,但只是一个想法:)

【讨论】:

  • 我曾尝试使用动态作为列表List&lt;dynamic&gt; 中的对象类型,但没有成功。正如您所提到的,将变量声明为简单的dynamic 确实可以编译,但功能与声明object 的列表相同,因此不幸的是,这对我没有任何好处。 :(
【解决方案4】:

如果您在像 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)

【讨论】:

  • 我在示例代码中使用 var 只是为了指定一个变量声明......实际上并不意味着规定使用 var 变量类型。我尝试了下面另一个回复中提到的dynamic 选项,但它的行为就像将变量声明为object 一样,这对我的问题没有帮助。 +1 示例。
  • Dynamic 的行为确实像 但不是。它为您提供了应该(但不是nesec。是!)存在于变量上的属性,而对象不存在。如果您至少提前知道一些事情,请尝试使用界面?
【解决方案5】:

另一个作弊:您可以在本地定义变量(类似于 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 内部返回数据,并在外部第二次返回默认信息。

【讨论】:

    【解决方案6】:

    这让我困扰了一段时间。最后,我构建了一些通用辅助方法,我可以在其中传递生成匿名对象的代码,并将 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多