我有这段代码:
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
}
我希望我的两种方法具有相同的名称。 这可能吗?
我的问题:
Nullable<T>
如果T
是值如果T
是引用类型,则为T
的类型和实例。 async
不允许ref / out,因此如果没有T
类型的方法参数,则不会推断T
,并且我的两个方法不能具有相同的名称(签名冲突) ,因为如果没有推断出T
,通用约束不适用于签名冲突解决方案目前这段代码有效,但我不喜欢“RequestValue1”和“RequestValue2”之间的这种奇怪的函数调用。
答案 0 :(得分:1)
您可以删除约束,并让调用者将Nullable<T>
类型传递给您的方法(即调用RequestValue<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
}
答案 1 :(得分:0)
可以有方法签名,如:
static void test1<T>(Nullable<T> param) where T:struct;
static void test1<T>(T param) where T:class;
没有冲突。尝试传递不可为空的结构类型将失败,但是在给定可为空类型或类类型的参数的情况下,编译器可以选择重载没有问题。
您的方案略有不同,因为您没有传递特定类型的参数;你只是试图传递这种类型。如果没有类型的实际参数,编译器将无法确定Nullable<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>
,它将T
与成功指标结合起来,其概念上类似于Nullable<T>
,但没有令人烦恼的struct
约束。它的参数类型。成功指标可以是bool
,也可以是如上所述的状态指示器。