c# - 具有可空引用类型的 out 参数

标签 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;
    }
}

为了查明一个选项是否包含一个值,我使用了这个利用模式匹配的扩展方法:

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;
}

我现在收到关于 return default; 的以下警告

Cannot convert null literal to non nullable reference or unconstrained type parameter

我不可能限制泛型参数Tclassstruct .

例如,如果我将通用参数限制为 class , 我无法生成 Option<int?>实例为 Nullable<int>类型是 struct本身。通过后缀声明 out 参数可为空 ?看起来也不是解决方案。

对我来说,类型系统在这个阶段有些破烂或没有经过深思熟虑。 Nullable 应该是 class或者需要像这样的通用参数限制:

public static bool TryGetValue<T>(this Option<T> option, out T value) 
    where T : nullable [...]

是否有其他方法可能适用于此问题?我错过了什么?

最佳答案

使用 MaybeNullWhenAttributeNotNullWhenAttribute .我推荐 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;
}

用法:

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.

该属性在 .Net standard 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; }
    }

(取自https://github.com/dotnet/runtime/blob/6077cf01f951a711a26a8d5970b211b6031b5158/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs#L45-L60)

关于c# - 具有可空引用类型的 out 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53759235/

相关文章:

c# - 如何在 C# 中为枚举类型应用 InterLocked.Exchange?

c# - 如何手动将数据添加到 dataGridView?

c# - 为什么范围索引对动态不起作用

c# - 为什么只读成员在结构中而不是在类中

c# - 给定对结构的托管引用,如何获取对偏移量字段的托管引用?

c# - 返回类型中引用类型的可空性与覆盖的成员不匹配

c# - 构造函数是在C#中初始化类中非空属性的唯一方法吗?

c# - 可空引用类型 : How to specify "T?" type without constraining to class or struct

c# - 剪刀石头布游戏——一个人连赢三场怎么结束?

c# - 找出哪个类调用了一个方法