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。您可以通过将数据声明为动态来逃避。或者只是将数据声明为元组列表。第二个代码块看起来不错。我将使用第二个代码段。!是的,那是最好的办法。