88

在研究实际上是抽象类的委托看到了以下我不明白的方法Delegate.cs

  • 为什么返回值使用?虽然它已经是一个引用()类型
  • ?[]?参数含义

你能解释一下吗?

public static Delegate? Combine(params Delegate?[]? delegates)
{
    if (delegates == null || delegates.Length == 0)
        return null;

    Delegate? d = delegates[0];
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}
4

3 回答 3

68

分步说明:

params Delegate?[] delegates- 它是一个可以为空的数组Delegate

params Delegate?[]? delegates- 整个数组可以为空

由于每个参数都是类型Delegate?并且您返回Delegate?[]?数组的索引,因此返回类型是有意义的,Delegate?否则编译器将返回错误,就像您正在返回并int从返回字符串的方法一样。

例如,您可以更改代码以返回Delegate如下类型:

public static Delegate Combine(params Delegate?[]? delegates)
{
    Delegate defaulDelegate = // someDelegate here
    if (delegates == null || delegates.Length == 0)
        return defaulDelegate;

    Delegate d = delegates[0] ?? defaulDelegate;
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}
于 2019-12-29T11:37:03.127 回答
26

可空引用类型是 C# 8.0 中的新内容,它们以前不存在。

这是一个文档问题,以及如何在编译时产生警告。

异常“对象未设置为对象的实例”异常很常见。但这是一个运行时异常,它可以在编译时部分发现。

对于监管Delegate d,您可以随时致电

 d.Invoke();

意思是,你可以编码它,在编译时什么都不会发生。它可能会在运行时引发异常。

而对于新的Delegate? p本准则

 p.Invoke();

将产生编译器警告。CS8602: Dereference of a possibly null reference 除非你写:

 p?.Invoke();

什么意思,只有在不为空时才调用。

因此,您记录的变量可能包含 null 或不包含。它会更早地发出警告,并且可以避免对 null 进行多次测试。与 int 和 int 相同吗?你肯定知道,一个不是空的 - 你知道如何将一个转换为另一个。

于 2019-12-29T12:24:22.490 回答
5

在 C# 8 中,应将引用类型显式标记为可为空。

默认情况下,这些类型不能包含 null,有点类似于值类型。虽然这不会改变引擎盖下的工作方式,但类型检查器将要求您手动执行此操作。

给定的代码被重构以使用 C# 8,但它并没有从这个新特性中受益。

public static Delegate? Combine(params Delegate?[]? delegates)
{
    // ...[]? delegates - is not null-safe, so check for null and emptiness
    if (delegates == null || delegates.Length == 0)
        return null;

    // Delegate? d - is not null-safe too
    Delegate? d = delegates[0];
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}

这是利用此功能的更新代码示例(不起作用,只是一个想法)。它使我们免于进行空值检查,并稍微简化了此方法。

public static Delegate? Combine(params Delegate[] delegates)
{
    // `...[] delegates` - is null-safe, so just check if array is empty
    if (delegates.Length == 0) return null;

    // `d` - is null-safe too, since we know for sure `delegates` is both not null and not empty
    Delegate d = delegates[0];

    for (int i = 1; i < delegates.Length; i++)
        // then here is a problem if `Combine` returns nullable
        // probably, we can add some null-checks here OR mark `d` as nullable
        d = Combine(d, delegates[i]);

    return d;
}
于 2019-12-29T20:30:39.377 回答