Declaring an implicitly typed variable inside conditional scope and using it outside
Asked Answered
A

7

5

In the simplified code below,

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

The variable MyObject is not accessible outside conditional block. How can I iterate outside the if..else ?

Appetizer answered 5/1, 2012 at 23:37 Comment(6)
I suppose you could declare the variable outside of the blocks.Veach
I get "Implicitly-typed local variables must be initialized"Appetizer
With x.* you mean the construction of an anonymous type, right? If not, why are you insisting on implicit typing?Bigoted
Yes I meant anonymous type when I wrote x.*. So in my actual code, the select looks like select new {columnA, columnB, columnC}. Sorry for oversimplification.Appetizer
In this case, since the conditional block is only being used to modify the where clause of the LINQ query, you can avoid the whole issue: eliminate the if block and change the where clause to where x.CostOfLiving == ((city == "New York City") ? "VERY HIGH" : "MODERATE"). In a more-complex case, replace the where clause with an appropriate generic predicate...Eterne
What I stupidly forgot to mention was that the WHERE will be absent in my else part. Instead of editing the code, I'm leaving it for context. In any case, Eric's suggestion worked for me. Thank you SOF.Appetizer
A
24

Let's clarify your confusing question. The problem is that you have two local variables, each of which has the same "unspeakable" type -- a sequence of anonymous type.

I would change your specific code like this:

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

However, if you still need to maintain the structure of the code as it is for some reason, you can do it like this:

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

This is a variation on a trick called "cast by example" where you give an example of an anonymous type to a generic method. Method type inference then figures out what the return type is, and uses that as the type of the implicitly typed local. At runtime, it does nothing but create a useless object that then gets discarded quickly.

Arnica answered 6/1, 2012 at 0:10 Comment(1)
This is, without a doubt, the smartest trick I've seen all year.Shinleaf
B
4

If you're using a named type, just declare a variable with that type before the if, but then the question would be trivial.

So I assume you're selecting an anonymous type, so you can't explicitly declare a variable with that type.

Cast by example would work here. But that doesn't feel like a good solution. Probably creating a named type is a better 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};
}

Or in your specific example one could project only after the conditional:

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

Or:

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

Or even just:

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

Which one is appropriate depends on how you simplified your question.

Bigoted answered 5/1, 2012 at 23:41 Comment(0)
J
3

Try this:

var ret = default(object);
Jook answered 19/11, 2013 at 11:44 Comment(0)
L
2

try this:

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>");
}
Laverne answered 14/11, 2012 at 12:32 Comment(0)
T
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>");    
Tello answered 5/1, 2012 at 23:40 Comment(0)
K
1

You will need to declare the variable outside of the scope of the if statement in order to use it in the foreach loop.

If the variable is declared but not initialized outside the if statement it can't be typed implicitly because the compiler won't have an expression to determine the type from.

If it's only going to be used in the foreach loop you can declare it as an IEnumerable.

Keishakeisling answered 5/1, 2012 at 23:44 Comment(0)
G
0

you'll have to define the MyObject as a var before the condition:

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

This will assign a schema to the MyObject variable.

Now you can proceed with your condition as:

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

}
Grimsley answered 5/1, 2012 at 23:40 Comment(2)
The extra dead query is unnecessary. Just write out the actual type.Veach
@Veach I assume the type is anonymous.Bigoted

© 2022 - 2024 — McMap. All rights reserved.