【问题标题】:The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable<T>'类型“T”必须是不可为空的值类型,才能将其用作泛型类型或方法“System.Nullable<T>”中的参数“T”
【发布时间】:2013-05-24 08:34:39
【问题描述】:

为什么我在以下代码中收到此错误?

void Main()
{
    int? a = 1;
    int? b = AddOne(1);
    a.Dump();
}

static Nullable<int> AddOne(Nullable<int> nullable)
{
    return ApplyFunction<int, int>(nullable, (int x) => x + 1);
}

static Nullable<T> ApplyFunction<T, TResult>(Nullable<T> nullable, Func<T, TResult> function)
{
    if (nullable.HasValue)
    {
        T unwrapped = nullable.Value;
        TResult result = function(unwrapped);
        return new Nullable<TResult>(result);
    }
    else
    {
        return new Nullable<T>();
    }
}

【问题讨论】:

  • 问题是什么??
  • 目前无法测试,但您调用ApplyFunction&lt;int, int&gt;而不是ApplyFunction&lt;int?, int&gt;
  • 为什么投反对票?对我来说似乎是一个合理的问题。

标签: c# generics nullable


【解决方案1】:

代码有几个问题。第一个是您的类型必须可以为空。您可以通过指定where T: struct 来表达这一点。您还需要指定 where TResult: struct,因为您也将其用作可空类型。

修复 where T: struct where TResult: struct 后,您还需要更改返回值类型(这是错误的)以及其他一些事情。

在修复所有这些错误并简化之后,您将得到以下结果:

static TResult? ApplyFunction<T, TResult>(T? nullable, Func<T, TResult> function)
                where T: struct 
                where TResult: struct
{
    if (nullable.HasValue)
        return function(nullable.Value);
    else
        return null;
}

请注意,您可以将Nullable&lt;T&gt; 重写为T?,这会使内容更具可读性。

您也可以使用?: 将其写为一个语句,但我认为它不那么可读:

return nullable.HasValue ? (TResult?) function(nullable.Value) : null;

您可能希望将其放入扩展方法中:

public static class NullableExt
{
    public static TResult? ApplyFunction<T, TResult>(this T? nullable, Func<T, TResult> function)
        where T: struct
        where TResult: struct
    {
        if (nullable.HasValue)
            return function(nullable.Value);
        else
            return null;
    }
}

然后你可以这样写代码:

int? x = 10;
double? x1 = x.ApplyFunction(i => Math.Sqrt(i));
Console.WriteLine(x1);

int? y = null;
double? y1 = y.ApplyFunction(i => Math.Sqrt(i));
Console.WriteLine(y1);

【讨论】:

  • 不写new TResult?(),写null不是更清楚吗?我猜这就是Nullable&lt;&gt; 的理念。
  • 而不是:返回 nullable.HasValue ? (TResult?) function(nullable.Value) : null;你可以返回 nullable??null;这有点更好,更具可读性
  • @SteveTemple 那么function() 是如何被调用的呢?
  • 对不起,误读了这行,如果你想调用一个不起作用的函数,你是对的
  • 您声明 return nullable.HasValue ? (TResult?) function(nullable.Value) : null; 不那么可读(我同意),但是如果您向该扩展方法添加参数:, TResult resultWhenNull = default(TResult) 那么您可以使方法主体更具可读性与return (nullable.HasValue) ? function(nullable.Value) : resultWhenNull;。另外它增加了一个特性:当你的 nullable 为 null 时,你可以指定默认值,但这只是一个可选参数,所以它不是必须始终传递的不便。 ;)
【解决方案2】:

正如错误提示的那样,编译器不能保证 T 不会已经可以为空。你需要给 T 添加一个约束:

static Nullable<T> ApplyFunction<T, TResult>(Nullable<T> nullable, 
    Func<T, TResult> function) : where T : struct 
                                 where TResult : struct

【讨论】:

  • 您需要进行更多更改才能使其正常工作。例如,TResult 也需要是一个结构体。
  • 没错,错过了TResult? 已修复:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多