一个表达式';s相当于return关键字

本文关键字:相当于 return 关键字 一个 表达式 | 更新日期: 2023-09-27 18:00:52

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
}

一个表达式';s相当于return关键字

第一个选项有什么问题?

我个人会坚持这个选择。它可读性强、通用性强,而且其他人可能最终维护您的代码时也能理解它。

由于非"函数语法",这在C#中是不可能的。(请参阅最底部的注释(。虽然条件运算符(?:(可以用于一些琐碎的地方,但它很快就会达到极限。而且,正如其他人所指出的,携带表达式的联合运算符(??(不支持"else"情况。因此,C#函数必须使用约定来实现类似的语义。下面讨论我处理这个问题的方法。

--

除了极少数例外,我不使用函数的早期返回。虽然C#没有"函数语法",但我仍然发现从函数开始到函数结束的代码风格是最清晰的——也就是说,只有最后一级分支上一条语句(可能是嵌套的(才能从函数返回,就好像条件本身(if/else if/else(是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.
}

由于我一直遵循这种模式,这有助于我更好地阅读/理解我的代码和流程。这种方法还避免了"过于棘手",并且只需在末尾添加else就可以很容易地扩展到处理"null case"。将赋值放在第一位并将分开可以使代码更简单,并允许使用var,我觉得这非常好。

快乐的编码。


我确实推高了条件并提前退出函数的一种情况是,在卫士中出现了异常。。。

if (argX == null) throw new ArgumentNullException("argX");

但这就是例外情况的本质。


实际上,这可以用类似于SmallTalk的扩展方法来完成。然而,在这种情况下,它只会带来更多的并发症。别把聪明眼镜戴得太久。想象一下:

public static void IfNotNull<T>(this T it, Action<T> action) {
    if (it != null) action(it);
}
GetX().IfNotNull((x) => {
    // "do stuff", x can't be null
});

不可能。??运算符的意思是"如果第一个参数不为null,请给我第一个参数,否则为第二个参数。"。不能将其用于流量控制。

根据方法的其余部分,空列表对类的其余部分没有影响吗?如果是这样,您可以使用:

List<Disc[,]> xNeverNull = GetX() ?? new List<Disc[,]>();

尽管List类是基于Arrays的,afair从一个小数组开始初始化Arrays,所以可能会有一些内存损失。如果你不需要修改列表,或者你不需要索引器,你可以考虑:

IEnumerable<Disc[,]> xNeverNull = GetX() ?? System.Linq.Enumerable.Empty<Disc[,]>();

ICollection<Disc[,]> xNeverNull = GetX() ?? new LinkedList<Disc[,]>();

你可以试试这个:

void Foo()
{
    List<Disc[,]> xNeverNull;
    if (null != (xNeverNull = GetX())
    {
    // do the stuff here
    }
}