2012-01-05 5 views
5

En el código simplificado a continuación,Declarar una variable implícita escrito dentro de alcance condicional y usarlo fuera

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>"); 
    } 

El MiObjeto variable no es accesible fuera del bloque condicional. ¿Cómo puedo iterar fuera del if..else?

+0

supongo que se podría declarar la variable fuera de los bloques. – ChaosPandion

+1

Obtengo "Se deben inicializar las variables locales implícitamente tipadas" – FMFF

+1

Con 'x. *' Te refieres a la construcción de un tipo anónimo, ¿no? Si no, ¿por qué insistes en tipear implícitamente? – CodesInChaos

Respuesta

24

Aclaremos su pregunta confusa. El problema es que tiene dos variables locales, cada una de las cuales tiene el mismo tipo "indescriptible": una secuencia de tipo anónimo.

que cambiaría su código específico de esta manera:

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

Sin embargo, si usted todavía tiene que mantener la estructura del código, ya que es por alguna razón, puede hacerlo de esta manera:

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

Esta es una variación de un truco llamado "cast por ejemplo" donde se da un ejemplo de un tipo anónimo a un método genérico.Luego, la inferencia del tipo de método determina cuál es el tipo de devolución y lo utiliza como el tipo de local implícitamente tipado. En tiempo de ejecución, no hace más que crear un objeto inútil que luego se descarta rápidamente.

+3

Este es, sin duda, el truco más inteligente que he visto en todo el año. – Polynomial

0

que tendrá que definir el MiObjeto como var antes de la condición:

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

Esto asignará un esquema para la variable MiObjeto.

Ahora puede continuar con su condición:

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

} 
+2

La consulta extra muerta es innecesaria. Solo escribe el tipo real. – ChaosPandion

+0

@ ChaosPandion Supongo que el tipo es anónimo. – CodesInChaos

+0

@ ChaosPandion, su derecha. – DoomerDGR8

1
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>");  
4

Si está utilizando un tipo llamado, simplemente declara una variable con ese tipo antes de la if, pero entonces la pregunta sería trivial .

Supongo que está seleccionando un tipo anónimo, por lo que no puede declarar explícitamente una variable con ese tipo.

Enviar por ejemplo funcionaría aquí. Pero eso no parece una buena solución. Probablemente, crear un tipo con nombre sea una mejor idea.

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}; 
} 

o en su ejemplo específico se podría proyectar sólo después de que el condicional:

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}); 

O:

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}); 

O incluso:

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}); 

Cuál es apropiado depende de cómo simp lified tu pregunta.

1

Deberá declarar la variable fuera del alcance de la instrucción if para usarla en el ciclo foreach.

Si la variable se declara pero no se inicializa fuera de la instrucción if, no se puede tipear implícitamente porque el compilador no tendrá una expresión para determinar el tipo.

Si solo se va a utilizar en el bucle foreach, puede declararlo como IEnumerable.

2

probar esto:

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>"); 
} 
Cuestiones relacionadas