当我在研究委托时,它实际上是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;
}
分步说明:
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;
}
可为空的引用类型是 C# 8.0 中的新增类型,以前不存在。
这是一个文档问题,以及如何在编译时生成警告。
异常"对象未设置为对象的实例"异常很常见。 但这是一个运行时异常,它已经在编译时部分发现。
对于调节Delegate d
您可以随时致电
d.Invoke();
这意味着,你可以对它进行编码,在编译时什么都不会发生。它可能会在运行时引发异常。
而对于本代码的新Delegate? p
p.Invoke();
将生成编译器警告。CS8602: Dereference of a possibly null reference
除非你写:
p?.Invoke();
什么意思,仅在不为空时才调用。
因此,您记录了一个变量可能包含 null 或不包含 null。它可以更早地引发警告,并且可以避免多次测试 null。与 int 和 int 相同?。您肯定知道,一个不是空的 - 并且您知道如何将一个转换为另一个。
在 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;
}