【问题标题】:Declaring an implicitly typed variable inside conditional scope and using it outside在条件范围内声明一个隐式类型变量并在外部使用它
【发布时间】:2012-02-03 19:24:54
【问题描述】:

在下面的简化代码中,

if(city == "New York City")
{
  var MyObject = from x in MyEFTable
                     where x.CostOfLiving == "VERY HIGH"
                     select x.*;

}
else
{
  var MyObject = from x in MyEFTable
                     where x.CostOfLiving == "MODERATE"
                     select x.*;

}

  foreach (var item in MyObject)
  {
     Console.WriteLine("<item's details>");
  }

在条件块之外无法访问变量 MyObject。如何在 if..else 之外进行迭代?

【问题讨论】:

  • 我想你可以在块之外声明变量。
  • 我得到“必须初始化隐式类型的局部变量”
  • x.* 是指匿名类型的构造,对吗?如果不是,你为什么坚持隐式类型?
  • 是的,我写 x.* 时的意思是匿名类型。所以在我的实际代码中,选择看起来像select new {columnA, columnB, columnC}。抱歉过于简单化了。
  • this 的情况下,由于条件块仅用于修改 LINQ 查询的 where 子句,您可以避免整个问题:消除 @987654325 @ 块并将where 子句更改为where x.CostOfLiving == ((city == "New York City") ? "VERY HIGH" : "MODERATE")。在更复杂的情况下,将where 子句替换为适当的泛型谓词...

标签: c# foreach var conditional-statements implicit-typing


【解决方案1】:

试试这个:

var ret = default(object);

【讨论】:

    【解决方案2】:

    试试这个:

    System.Linq.IQueryable<MyEFTable Object type> MyObject = null;
    if(city == "New York City")
    {
      MyObject = from x in MyEFTable
                 where x.CostOfLiving == "VERY HIGH"
                 select x.*;
    }
    else
    {
      MyObject = from x in MyEFTable
                 where x.CostOfLiving == "MODERATE"
                 select x.*;
    }
    
    foreach (var item in MyObject)
    {
      Console.WriteLine("<item's details>");
    }
    

    【讨论】:

      【解决方案3】:

      让我们澄清一下您的困惑问题。问题是您有两个局部变量,每个变量都具有相同的“不可描述”类型——一系列匿名类型。

      我会像这样更改您的特定代码:

      string cost = city == "NYC" ? "HIGH" : "MODERATE";
      var query = from row in table 
                  where row.Cost == cost 
                  select new { row.Population, row.Elevation };
      

      但是,如果由于某种原因您仍然需要保持代码结构不变,您可以这样做:

      static IEnumerable<T> SequenceByExample<T>(T t){ return null; }
      ...
      var query = SequenceByExample(new { Population = 0, Elevation = 0.0 } );
      if (whatever)
          query = ...
      else
          query = ...
      

      这是一种称为“通过示例强制转换”的技巧的变体,在该技巧中,您将匿名类型的示例提供给泛型方法。方法类型推断然后确定返回类型是什么,并将其用作隐式类型本地的类型。在运行时,它只会创建一个无用的对象,然后很快就会被丢弃。

      【讨论】:

      • 毫无疑问,这是我一年来见过的最聪明的把戏。
      【解决方案4】:

      如果您使用的是命名类型,只需在 if 之前声明一个具有该类型的变量,但这样问题就很简单了。

      所以我假设您选择的是匿名类型,因此您不能显式声明具有该类型的变量。

      举个例子在这里可以工作。但这感觉不是一个好的解决方案。可能创建一个命名类型是一个更好的主意。

      var myObject =Enumerable.Empty<RowType>.Select(row=>select new {columnA, columnB, columnC});
      if(city == "New York City")
      {
        myObject= from x in MyEFTable
                           where x.CostOfLiving == "VERY HIGH"
                           select select new {columnA, columnB, columnC};
      }
      else
      {
        myObject = from x in MyEFTable
                           where x.CostOfLiving == "MODERATE"
                           select select new {columnA, columnB, columnC};
      }
      

      或者在您的具体示例中,只能在条件之后进行投影:

      IQueryable<RowType> partialQuery;
      if(city == "New York City")
          partialQuery=MyEFTable.Where(x=>x.x.CostOfLiving == "VERY HIGH");
      else
          partialQuery=MyEFTable.Where(x=>x.x.CostOfLiving == "MODERATE");
      var myObject=partialQuery.Select(x=>x.new {columnA, columnB, columnC});
      

      或者:

      Expression<Predicate<RowType>> filter;//Note that this is an Expression, not just a delegate
      if(city == "New York City")
        filter=x=>x.x.CostOfLiving == "VERY HIGH";
      else
        filter=x=>x.x.CostOfLiving == "MODERATE";
      var myObject=MyEFTable.Where(filter).Select(x=>x.new {columnA, columnB, columnC});
      

      甚至只是:

      string s;
      if(city == "New York City")
        s="VERY HIGH";
      else
        s="MODERATE";
      var myObject=MyEFTable.Where(x=>x.CostOfLiving == s).Select(x=>x.new {columnA, columnB, columnC});
      

      哪一个合适取决于您如何简化问题。

      【讨论】:

        【解决方案5】:
        List<MyObject> list = null; 
        
        if(city == "New York City")    
           list = (from x in MyEFTable  where x.CostOfLiving == "VERY HIGH"
                             select x.*).ToList();       
        else    
           list = (from x in MyEFTable where x.CostOfLiving == "MODERATE"
                             select x.*).ToList();        
        
        foreach (var item in list)   
             Console.WriteLine("<item's details>");    
        

        【讨论】:

          【解决方案6】:

          您需要在 if 语句范围之外声明变量,以便在 foreach 循环中使用它。

          如果变量已声明但未在 if 语句之外初始化,则无法隐式键入,因为编译器没有表达式来确定类型。

          如果它只用于 foreach 循环,您可以将其声明为 IEnumerable。

          【讨论】:

            【解决方案7】:

            您必须在条件之前将 MyObject 定义为 var:

            var MyObject = from x in MyEFTable
                                 where x.CostOfLiving == "SOMETHING THAT'LL RETURN NO ROWS"
                                 select x.*;
            

            这将为 MyObject 变量分配一个架构。

            现在您可以按照以下方式处理您的情况:

            if(city == "New York City")
            {
              MyObject = from x in MyEFTable
                                 where x.CostOfLiving == "VERY HIGH"
                                 select x.*;
            
            }
            else
            {
              MyObject = from x in MyEFTable
                                 where x.CostOfLiving == "MODERATE"
                                 select x.*;
            
            }
            

            【讨论】:

            • 额外的死查询是不必要的。只需写出实际类型即可。
            • @ChaosPandion 我假设类型是匿名的。
            猜你喜欢
            • 2017-12-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-01-03
            • 1970-01-01
            • 1970-01-01
            • 2018-10-14
            相关资源
            最近更新 更多