C#不能使`notnull`类型为可空 - c#

我正在尝试创建类似于Rust的Result或Haskell的Either的类型,到目前为止,我已经做到了:

public struct Result<TResult, TError>
    where TResult : notnull
    where TError : notnull
{
    private readonly OneOf<TResult, TError> Value;
    public Result(TResult result) => Value = result;
    public Result(TError error) => Value = error;

    public static implicit operator Result<TResult, TError>(TResult result)
        => new Result<TResult, TError>(result);

    public static implicit operator Result<TResult, TError>(TError error)
        => new Result<TResult, TError>(error);

    public void Deconstruct(out TResult? result, out TError? error)
    {
        result = (Value.IsT0) ? Value.AsT0 : (TResult?)null;
        error = (Value.IsT1) ? Value.AsT1 : (TError?)null;
    }  
}

鉴于两个类型参数都被限制为notnull,为什么会抱怨(在后面带有可空?符号的类型参数的任何地方):

必须知道可为空的类型参数是值类型或不可为空的引用类型。考虑添加“类”,“结构”或类型约束。

我在启用了可为空的引用类型的.NET Core 3上使用C#8。

参考方案

基本上,您是在寻求IL无法代表的东西。可空值类型和可空引用类型是非常不同的野兽,尽管它们在源代码中看起来相似,但IL却大不相同。值类型T的可空版本是另一种类型(Nullable<T>),而引用类型T的可空版本是同一类型,其属性告诉编译器期望什么。

考虑以下简单示例:

public class Foo<T> where T : notnull
{
    public T? GetNullValue() => 
}

由于相同的原因,这是无效的。

如果我们将T约束为一个结构,则为GetNullValue方法生成的IL将具有Nullable<T>的返回类型。

如果我们将T约束为不可为空的引用类型,则为GetNullValue方法生成的IL将具有T的返回类型,但具有可为空性方面的属性。

编译器无法为同时具有TNullable<T>的返回类型的方法生成IL。

这基本上是所有可空引用类型根本不是CLR概念的结果-这只是编译器的魔力,可以帮助您在代码中表达意图并让编译器在编译时执行一些检查。

错误消息不是很清楚。已知T是“值类型或非空引用类型”。更精确(但明显多于其他)的错误消息是:

可为空的类型参数必须已知为值类型,或已知为不可为空的引用类型。考虑添加“类”,“结构”或类型约束。

到那时,错误将合理地应用于我们的代码-type参数不是“已知为值类型”,也不是“已知为非空引用类型”。众所周知这是两者之一,但是编译器需要知道哪一个。

与哪些运算符>>兼容 - java

我这里没有什么代码int b=3; b=b >> 1; System.out.println(b); 它可以完美工作,但是当我将变量b更改为byte,short,float,double时,它包含错误,但是对于变量int和long来说,它可以完美工作,为什么它不能与其他变量一起工作? 参考方案 位移位运算符(例如>>)与任何整数类型兼…

>> Python中的运算符 - python

>>运算符做什么?例如,以下操作10 >> 1 = 5有什么作用? 参考方案 它是右移运算符,将所有位“右移”一次。二进制10是1010移到右边变成0101这是5

Python 3运算符>>打印到文件 - python

我有以下Python代码编写项目的依赖文件。它可以在Python 2.x上正常工作,但是在使用Python 3进行测试时会报告错误。depend = None if not nmake: depend = open(".depend", "a") dependmak = open(".depend.mak&#…

剃刀付款集成->如何通过关闭按钮X检测剃刀付款模型是否关闭 - javascript

当用户关闭而无需付款时,我在CI框架中使用Razorpay,请创建razor支付模型,然后取消订单,我希望按状态更改为已取消的状态触发查询。所以我怎么能检测到这一点。我已经通过单击jQuery单击关闭功能但无法使用... javascript大神给出的解决方案 Razorpay提供了JS方法来检测模式关闭。您编写的任何JS代码都不会在结帐页面上运行,因为它是…

如何知道是否由父母造成了回合(A => B => C => A) - c#

我有以下结构:[Employee] ID Manager1ID Manager2ID 场景:我要进行验证,以确保所选的Manager1或Manager2不会引起回合。换句话说,我想知道这种情况是否存在:A的经理是B,B的经理是C,C的经理也是A //无效A => B => C => A告诉用户A不是C的有效管理员,因为C已经是A的管理员。问…