2012-01-05 61 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);