Seb*_*ull 5 c# c#-8.0 nullable-reference-types
我为我Option的一些项目实现了一种类型,如下所示:
public abstract Option<T> {}
public class None<T> : Option<T>
public class Some<T> : Option<T>
{
public T Value { get; }
public Some(T value)
{
Value = value;
}
}
Run Code Online (Sandbox Code Playgroud)
为了找出一个 Option 是否包含一个值,我使用了这个利用模式匹配的扩展方法:
public static bool TryGetValue<T>(this Option<T> option, out T value)
{
if (option is Some<T> some)
{
value = some.Value;
return true;
}
value = default;
return false;
}
Run Code Online (Sandbox Code Playgroud)
我现在收到以下警告 return default;
无法将空文字转换为不可为空的引用或不受约束的类型参数
我不可能将泛型参数限制T为classor struct。
例如,如果我将泛型参数限制为class,则无法生成Option<int?>实例,因为Nullable<int>类型是 astruct本身。通过后缀将 out 参数声明为可为空?也不是解决方案。
对我来说,在这个阶段,类型系统有些破损或没有经过彻底的考虑。Nullable 应该是 aclass或者需要有一个通用参数限制,例如:
public static bool TryGetValue<T>(this Option<T> option, out T value)
where T : nullable [...]
Run Code Online (Sandbox Code Playgroud)
是否有另一种方法可能适合此问题?我错过了什么?
使用MaybeNullWhenAttribute或NotNullWhenAttribute。我推荐MaybeNullWhen它,因为它甚至适用于不受结构或引用类型约束的类型参数。
public static bool TryGetValue<T>(this Option<T> option, [MaybeNullWhen(false)] out T value)
{
if (option is Some<T> some)
{
value = some.Value;
return true;
}
value = default;
return false;
}
Run Code Online (Sandbox Code Playgroud)
用法:
if(option.TryGetValue(out var value))
{
value.SomeMethod(); // no warning - value is known to be non-null here
}
value.SomeMethod(); // warning - value may be null here.
Run Code Online (Sandbox Code Playgroud)
该属性在 .Net 标准 2.1/.new core 3.0 之前不可用,但如果不可用,您可以自己手动定义它。确保它是内部的,否则如果另一个库也将其定义为 public 并且有人从这两个库中继承,则会导致冲突:
namespace System.Diagnostics.CodeAnalysis
{
/// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter may be null even if the corresponding type disallows it.</summary>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class MaybeNullWhenAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified return value condition.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter may be null.
/// </param>
public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
/// <summary>Gets the return value condition.</summary>
public bool ReturnValue { get; }
}
Run Code Online (Sandbox Code Playgroud)