2012-01-05 20 views
5

使用它在下面的簡化的代碼,聲明條件範圍內的隱式類型的變量和外部

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之外迭代?

+0

我想你可以聲明塊外面的變量。 – ChaosPandion 2012-01-05 23:39:19

+1

我得到「隱式類型的局部變量必須被初始化」 – FMFF 2012-01-05 23:41:21

+1

用'x。*'表示構造一個匿名類型,對吧?如果不是,你爲什麼堅持隱式鍵入? – CodesInChaos 2012-01-05 23:46:33

回答

24

讓我們來澄清你令人困惑的問題。問題是你有兩個局部變量,每個局部變量都有相同的「不可說」類型 - 一個匿名類型的序列。

我會改變你的具體代碼如下:

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

這是一個叫做「按實例轉換」的技巧的變體,您將匿名類型的示例提供給泛型方法。方法類型推斷然後找出返回類型是什麼,並使用它作爲隱式類型的本地類型。在運行時,它只會創建一個無用的對象,然後很快被丟棄。

+3

毫無疑問,這是我見過的最聰明的技巧。 – Polynomial 2012-10-10 15:30:58

0

你必須定義爲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.*; 

} 
+2

額外的死查詢是不必要的。只需寫出實際的類型。 – ChaosPandion 2012-01-05 23:41:15

+0

@ChaosPandion我認爲這個類型是匿名的。 – CodesInChaos 2012-01-05 23:45:27

+0

@ChaosPandion,你的權利。 – DoomerDGR8 2012-01-09 07:24:41

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

如果您使用的是命名類型,只是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}); 

哪一個適當取決於你如何簡化明確了你的問題。

1

您將需要在if語句的範圍之外聲明變量,以便在foreach循環中使用它。

如果在if語句之外聲明變量但未初始化變量,則不能隱式鍵入變量,因爲編譯器不會有表達式來確定變量的類型。

如果只在foreach循環中使用,您可以將其聲明爲IEnumerable。

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

試試這個:

var ret = default(object);