C# 必须初始化隐式类型的局部变量

C# 必须初始化隐式类型的局部变量,c#,asp.net-mvc,linq,C#,Asp.net Mvc,Linq,我想动态地设置如下条件:- var data; if(employeId != 0) { data = (from a in ctx.tblTO1 join b in ctx.tblTO2 on a.Company equals b.Company where a.Id == b.Id && a.employeeId == emplo

我想动态地设置如下条件:-

var data;
if(employeId != 0) {
 data = (from a in ctx.tblTO1
             join b in ctx.tblTO2
                    on a.Company equals b.Company
                    where a.Id == b.Id &&
                    a.employeeId == employeeId
                    select new { a = a, b = b }).ToList();
}else{
     data = (from a in ctx.tblTO1
                 join b in ctx.tblTO2
                        on a.Company equals b.Company
                        where a.Id == b.Id &&
                        a.Cat == cats
                        select new { a = a, b = b }).ToList();
}
上述表达式的结果为匿名类型。所以我不能声明它&第一行给出了错误<代码>隐式类型的局部变量必须初始化


解决这个问题的方法是什么?我们可以使用单独的函数吗?那么函数的返回类型是什么呢?

您可以使用DTO类而不是匿名类型。Resharper可以为您实现这一转变。或者,您可以在此处使用条件运算符允许类型推断工作:

var data = employeId != 0 ? (query1) : (query2);
那可不好看

还有另一个黑客:

var data = new [] { new { a = 0, b = 0 } }.ToList();

这将创建一个虚拟对象,使
var
类型推断工作。您可能不应该这样做…

您可以按如下方式重写查询

var data = (from a in ctx.tblTO1
                 join b in ctx.tblTO2
                        on a.Company equals b.Company
                        where a.Id == b.Id &&
                        ((a.Cat == cats && employeId==0)||
                         (a.employeeId == employeeId))
                        select new { a = a, b = b }).ToList();
(from a in ctx.tblTO1
         join b in ctx.tblTO2
                on a.Company equals b.Company
                where a.Id == b.Id &&
                ( (employeId != 0 && a.employeeId == employeeId) || (a.Cat == cats))
                select new { a = a, b = b }).ToList();

var数据
不可能工作,因为
var
只针对初始化器进行解析,而不针对任何后续赋值

您有两个主要的选择:要么停止使用匿名类型,要么确保您有一个初始化器。其中第一个可能看起来像:

class MyClass {
    public T01 a;
    public T02 b;
}
现在,您可以使用
List

第二个选项可以分解为两个子选项:可以重新处理现有逻辑以适应单个表达式,也可以使用虚拟值进行初始化

第一个可能看起来像
var data=condition?问题1:问题2


第二个可能看起来像
var data=true?null:query1
,其中,
query1
实际上从未得到计算,它只是用来确定
数据的类型

您不能只隐式声明变量,而不给它任何值。 当你写作时:

var a = "foo";
这意味着,您有一个类型为
string
的变量,而不仅仅是一个值为string的变量。编译器需要知道确切的类型是什么,即使类型是从用法中隐含的

当您只编写声明
var a
时,编译器不知道如何处理它。它是一个
对象
?可能是
字符串
?一个号码?要在堆栈上分配多少内存

使用静态类型语言
C #
如果声明变量,请声明类型。 您可以这样做:

object data;
// rest of your code

当然,
var数据毫无意义

您可以使用适当的字段定义一个类型作为元素类型。如果同一类型出现不止一次,这一点尤其有用

您也可以使用
?:
此处使用的
if…else

var data = (employeeId != 0)
  ? (from a in ctx.tblTO1
     join b in ctx.tblTO2
      on a.Company equals b.Company
      where a.Id == b.Id &&
        a.employeeId == employeeId
        select new { a = a, b = b }).ToList()
  : (from a in ctx.tblTO1
     join b in ctx.tblTO2
       on a.Company equals b.Company
       where a.Id == b.Id &&
         a.Cat == cats
         select new { a = a, b = b }).ToList();
但最清楚的可能是修改查询,以了解每种情况的不同之处:

var query = from a in ctx.tblTO1
            join b in ctx.tblTO2
            on a.Company equals b.Company
            where a.Id == b.Id
            select new { a = a, b = b };

if (employeeId != 0)
  query = query.Where(i => i.a.employeeId == employeeId);
else
   query = query.Where(i => i.a.Cat == cats);
var data = query.ToList();

这样做的好处是在代码中更清楚地区分这两种情况。如果您以不再需要的方式更改代码,则将
ToList()
分离出来还有一个好处,那就是可以使用
dynamic
关键字,而不是
var
。您可以在以下MSDN官方网站上找到更多信息:

第页的一些代码片段:

Visual C#2010引入了一种新类型,即动态。类型是静态的 类型,但类型为dynamic的对象会绕过静态类型检查。在里面 大多数情况下,它的功能就像它有类型对象一样。在编译时 假定类型为动态的元素支持任何操作

这是var关键字的另一种选择。但我认为你们可以通过在where子句中设置条件来避免动态,正如本页提到的其他答案一样

 .Where(a=> (a.EmployeeId != 0 && a.EmployeeId == employeeId) || your other conditions)

这是一个有效的解决方案,但它可能无法使用任何索引。它将能够使用索引。我看不出有什么理由不能这样做。
|
通常会导致SQL Server中没有使用索引。索引不能用于在两个不同的列上搜索。@usr是否将
|
逻辑一直传递到此处生成的SQL,对于用于简化用于一个分支或另一个分支的代码的给定调用,
employeeId==0
始终为false或true,而不是这样的事实?@JonHanna我所知的没有LINQ提供程序执行这种简化。这应该以类似于
@p0=0和…
的方式到达SQL Server。您可以通过将数据声明为动态来逃避。或者只是将数据声明为元组列表。第二个代码块看起来不错。我将使用第二个代码段。!是的,那是最好的办法。