有条件地分配C#var:尽可能优雅?

有条件地分配C#var:尽可能优雅?,c#,type-inference,C#,Type Inference,我理解C#关键字var意味着编译时的类型,因此需要在同一位置声明和赋值,从而使以下构造非法: var something; if (condition) { something=1; } else { something = 0; } 尽管C#编译器基本上可以确定当前作用域中的所有赋值结果都是相同的类型,但它(目前)不会,因此会生成编译时错误 在将var与LINQ一起使用时,有时我希望根据程序条件对结果变量进行稍微不同的初始化。我发现的方法是使用?:运算符,如: var pa

我理解C#关键字var意味着编译时的类型,因此需要在同一位置声明和赋值,从而使以下构造非法:

var something;

if (condition)
{
    something=1;
}
else
{
    something = 0;
}
尽管C#编译器基本上可以确定当前作用域中的所有赋值结果都是相同的类型,但它(目前)不会,因此会生成编译时错误

在将var与LINQ一起使用时,有时我希望根据程序条件对结果变量进行稍微不同的初始化。我发现的方法是使用?:运算符,如:

var participants = (email == null ?
                   (from part in db.Participant
                    where part.SequenceNumber == seqNr
                    select part)
                   :
                   (from part in db.Participant
                    where part.EmailAddress == email
                    select part));
如果我只有两个可能的任务,这就足够了,但是如果有多个可能的任务,这很快就会变得很难处理

有更优雅的方法吗?

您可以使用
。其中(…)
而不是查询语法:

var participants = email == null
    ? db.Participant.Where(p => p.SequenceNumber == seqNr)
    : db.Participant.Where(p => p.EmailAddress == email);
但就个人而言,我不会在这里使用
var
——它的规模不会超过2,但这是一个经典的“搜索”模式。我可以使用:

IQueryable<Part> query = db.Participant;
if(email != null) query = query.Where(p => p.EmailAddress == email);
if(seqNr != null) query = query.Where(p => p.SequenceNumber == seqNr);
...
// consume query
IQueryable查询=db.Participant;
if(email!=null)query=query.Where(p=>p.EmailAddress==email);
if(seqNr!=null)query=query.Where(p=>p.SequenceNumber==seqNr);
...
//消费查询

这允许为更具体的查询组合多个条件(在本例中为“AND”)。您也可以使用“或”,但它稍微复杂一些(除非您使用的是凌乱的
Concat
/
Union

我认为更优雅的方法是将代码分解成这样一种方式,即使用一个方法来处理每个不同的程序条件

即:

if (email == null) {
    DoStuffWhenEmailIsNull();
}
else {
    DoStuffWhenEmailIsNotNull();
}

更重要的是,它允许您根据参数对结果进行不同的排序。动态
OrderBy
的工作原理非常相似,但是查询语法非常复杂。除了“Stuff”在每种情况下都是相同的之外,只是选择结果集的方法不同。这种方法要么会导致冗余的处理代码,要么只是将问题转移到这两种新方法所使用的方法上。嗯,有些语言允许在var声明点之后进行推理……如果C#在某种程度上不能更聪明地进行类型推理,我会感到惊讶。只要当前作用域中的所有赋值尝试同时赋值,编译器就可以处理这种情况。我同意原则上这是可以做到的,但实际上这比你的速写要复杂得多。var不仅要求存在初始值设定项,还要求初始值设定项不引用变量。如果你有int M(out int),那么你可以说“int x=M(out x);”,但你不能说“var x=M(out x);”,因为要对M进行重载解析,我们需要知道x的类型,这就是我们试图弄清楚的。说“var s;if(b)M(out s);else s=0;”是否合法?C#3类型的推断器不是我见过的最聪明的。大多数函数式语言都要好得多,而且haXe作为一种命令式语言,有一个非常强大的推断器,它也可以推断超出初始化点的内容。例如,在Eric Lippert的案例中,类型将取决于之后的用途。如果将其用作int类型的函数参数,则该变量将被推断为int。编译器只需查看它所使用的每个位置,它是什么类型,并基于此推断类型。如果需要动态的,实际上,这就是定理。推断器是一个有点缺陷的自动取款机。