Объявление неявно типизированной переменной внутри условной области и использование ее вне - PullRequest
5 голосов
/ 06 января 2012

В приведенном ниже упрощенном коде

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?

Ответы [ 7 ]

24 голосов
/ 06 января 2012

Давайте уточним ваш запутанный вопрос. Проблема в том, что у вас есть две локальные переменные, каждая из которых имеет один и тот же «невыразимый» тип - последовательность анонимного типа.

Я бы изменил ваш конкретный код следующим образом:

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 = ...

Это вариант трюка под названием «приведение примера», в котором вы даете пример анонимного типа универсальному методу. Вывод типа метода затем выясняет, что является возвращаемым типом, и использует его в качестве типа неявно типизированного local. Во время выполнения он только создает бесполезный объект, который затем быстро удаляется.

4 голосов
/ 06 января 2012

Если вы используете именованный тип, просто объявите переменную с этим типом перед 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});

Какой из них подходит, зависит от того, как вы упростили свой вопрос.

3 голосов
/ 19 ноября 2013

Попробуйте это:

var ret = default(object);
2 голосов
/ 14 ноября 2012

попробуйте это:

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>");
}
1 голос
/ 06 января 2012

Вам потребуется объявить переменную вне области действия оператора if, чтобы использовать ее в цикле foreach.

Если переменная объявлена, но не инициализирована вне оператора if, она не может быть введена неявно, поскольку у компилятора не будет выражения для определения типа из.

Если она только собираетсядля использования в цикле foreach вы можете объявить его как IEnumerable.

1 голос
/ 06 января 2012
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>");    
0 голосов
/ 06 января 2012

вам нужно будет определить MyObject как переменную перед условием:

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.*;

}
...