5

我有这个代码:

public async static Task<T?> RequestValue1<T>(Command requestCommand)
                    where T : struct 
{
    // Whatever
}

public async static Task<T> RequestValue2<T>(Command requestCommand)
                    where T : class 
{
    // Whatever
}

我想为我的两种方法使用相同的名称。这甚至可能吗?

我的问题:

  • 我必须编写两种不同的方法,因为返回类型(如果请求失败,我希望它为 null,如果请求成功,我希望它为值),即Nullable<T>ifT是值类型,Tif的实例T是引用类型。
  • async不允许引用/输出,因此如果没有 type 的方法参数T,则不会推断,并且我的两个方法不能具有相同的名称(签名冲突,因为如果不推断T,通用约束不适用于签名冲突解决)T

目前这段代码有效,但我不喜欢“RequestValue1”和“RequestValue2”之间的这个奇怪的函数调用。

4

3 回答 3

3

您可以创建自己的Option类型并使用它来指示是否返回值:

public async static Task<Option<T>> RequestValue<T>(Command requestCommand) {
  ...
}

更新:该Option<T>类型的目的是替换nulls 和Nullable<T>s,但如果您仍想使用它们,可以使用这些扩展方法来弥补差距:

public static class OptionExtensions {
  public static T? GetNullableValue<T>(this Option<T> option) where T : struct {
    return option.HasValue ? (T?)option.Value : null;
  }
  public static T GetValueOrNull<T>(this Option<T> option) where T : class {
    return option.HasValue ? option.Value : null;
  }
}
于 2012-12-19T14:53:35.937 回答
1

您可以删除约束,并让调用者将Nullable<T>类型传递给您的方法(即 callRequestValue<int?>(cmd)而不是RequestValue<int>(cmd))。您可以在运行时确保可空性,如下所示:

public async static Task<T> RequestValue<T>(object arg) {
    var t = typeof (T);
    if (!t.IsClass && (!t.IsGenericType || t.GetGenericTypeDefinition() != typeof(Nullable<>))) {
        throw new ArgumentException("T");
    }
    // Whatever
}
于 2012-12-19T15:01:40.177 回答
0

一个可以有方法签名,如:

    static void test1<T>(Nullable<T> param) where T:struct;
    static void test1<T>(T param) where T:class;

没有冲突。尝试传递不可为空的结构类型将失败,但编译器在给定可空类型或类类型的参数的情况下选择重载没有问题。

您的情况有点不同,因为您没有传递特定类型的参数;你只是想传递类型本身。如果没有该类型的实际参数,编译器将无法确定 aNullable<T>比另一种更适合一种方法。我的倾向是提供一种方法,该方法使用结果的无效性以外的其他方式来指示成功或失败。正常Try模式如下所示:

static bool RequestValue1<T>(Command requestCommand, out Task<T> Result);

我不是特别喜欢这种模式,因为不可能Result协变或参与类型推断。另一种选择是:

static Task<T> RequestValue1<T>(Command requestCommand, out bool Success);

这样的形式在协方差方面没有问题。另一种形式是:

static Task<T> RequestValue1<T>(Command requestCommand, out ResultStatus Status);

其中 ResultStatus 将是一个类型,其Succeeded方法True在成功的情况下返回,但可能有其他成员解释在失败的情况下出了什么问题。如果它是一个不可变的抽象类型,它定义了一个单例Success实例以供在事情工作时使用,那么它可以在将来扩展以在事情不工作时提供任意级别的细节,而不会在它们工作时造成任何 GC 压力。

不幸的是,即使是out参数类型不依赖的形式T也不能在某些情况下使用。为此,可以定义一个结构类型CommandResult<T>,它将 aT与成功指示符组合在一起,其方式在概念上类似于但对其参数类型Nullable<T>没有烦人的约束。struct成功指示符可以是bool,也可以是如上所述的状态指示符。

于 2012-12-19T16:29:38.927 回答