void Foo()
{
var xMaybeNull = GetX();
if (xMabyeNull == null) return; // Some way to get rid of this extra
// sentence without loosing the check
// do stuff
}
简单的方法就是这样,但编译器需要一个表达式。
void Foo()
{
List<Disc[,]> xNeverNull = GetX() ?? return;
// do stuff
}
问题是,有没有办法编写someSortOfReturnExpression
(我猜不是)或其他解决方案,可以在一行上找到我想要的内容?
void Foo()
{
List<Disc[,]> xNeverNull = GetX() ?? someSortOfReturnExpression;
// do stuff
}
答案 0 :(得分:8)
第一个选项出了什么问题?
我个人坚持这个选择。可能最终维护代码的其他人可读,常见且易懂。
答案 1 :(得分:1)
不可能。 ??
运算符意味着'如果它不为null,则给我第一个参数,否则为第二个参数。您无法将其用于流量控制。
答案 2 :(得分:1)
由于非“功能语法”,这在C#中是不可能实现的。 (请参阅最底部的注释)。虽然条件运算符(?:
)可以在一些琐碎的地方使用,但它很快就会遇到限制。并且,正如其他人所指出的那样,结合表达式的合并运算符(??
)不支持“其他”情况。因此,C#函数必须使用约定来实现类似的语义。以下讨论了我解决这个问题的方法。
-
除了极少数例外,我不使用函数的早期返回。虽然C#没有“功能语法”,但我仍然发现从函数的开头到函数结尾的代码样式最清晰 - 也就是说,只有最后一个语句 最后一级分支(可能是嵌套的)可以从函数返回,就像条件本身(if/else if/else
)是一个表达式(如?:
)那样{{ 1}}编辑一个值。 (如果分支太多,则可能表示函数太大。)
在大多数情况下,我会将代码编写如下:
return
由于我一直遵循这种模式,它可以帮助我更好地阅读/理解我的代码和流程。这种方法也避免了“过于棘手”,只需将void Foo()
{
var xMaybeNull = GetX();
if (xMabyeNull != null) {
// Know it's valid to use xMaybeNull in here -- can't be null.
// "do stuff"
}
// xMaybeNull may be null here. So don't put anything here
// that requires otherwise. In this case the flow will just "drop off"
// so the `return` is completely omitted.
}
添加到最后,就可以非常容易地扩展以处理“null case”。保持作业的第一个和分开使代码更简单,并允许使用else
,我发现它非常好。
快乐的编码。
我确实推高了条件和早期功能退出的一个案例是在警卫中提出例外 ......
var
......但这是例外的本质。
实际上,可以以类似于SmallTalk的方式使用扩展方法完成。但是,在这种情况下,它只会引入更多的复杂情况。不要让Cleverness Goggles保持太长时间。想象一下:
if (argX == null) throw new ArgumentNullException("argX");
答案 3 :(得分:0)
根据方法的其余部分,空列表是否会对您班级的其余部分产生影响?如果是这样,你可以使用:
List<Disc[,]> xNeverNull = GetX() ?? new List<Disc[,]>();
虽然List类是基于Arrays的,但是它首先用一个小数组初始化,因此可能会有一些内存损失。如果您不必修改列表,或者您不需要索引器,则可以考虑:
IEnumerable<Disc[,]> xNeverNull = GetX() ?? System.Linq.Enumerable.Empty<Disc[,]>();
或
ICollection<Disc[,]> xNeverNull = GetX() ?? new LinkedList<Disc[,]>();
答案 4 :(得分:0)
你可以试试这个:
void Foo()
{
List<Disc[,]> xNeverNull;
if (null != (xNeverNull = GetX())
{
// do the stuff here
}
}