双泛型函数的语法糖

本文关键字:语法 函数 泛型 | 更新日期: 2023-09-27 18:10:33

我在c#中有以下函数:

bool Handle<TCommandHandler, TModel>(TModel model) where TCommandHandler : ICommandHandler<TModel> {
    // ...
    _container.Resolve<TCommandHandler>();
    // ...
}

由于TModel从函数参数中是明确的,所以我希望在调用函数时不指定其类型。理想情况下,我想这样命名它:

Handle<MyCommandHandler>(model);

由于这可能是不可能的,我想到了以下内容:

HandleTemp<TModel> Handle<TModel>(TModel model) {
    return new HandleTemp<TModel>(model);
}
public class HandleTemp<TModel> {
    private TModel _model;
    public HandleTemp(TModel model) { _model = model;}
    public bool With<TCommandHandler>() where TCommandHandler : ICommandHandler<TModel> {
    }
}

我现在把它命名为:

Handle(model).With<MyCommandHandler>();

还有其他可能吗?我的解决方案是否完全错了?

双泛型函数的语法糖

不,你的分析和解决方案看起来是对的。实际上,泛型类型推断只能在全有或全无的基础上工作。如果有一些泛型参数无法推断,则必须显式声明所有参数。就我个人而言,我很想说"你担心这些参数,我会告诉你这个",但是……那是不存在的

唯一的其他选择是添加一个人工的额外的规则参数,以允许它推断出泛型参数——有点讨厌。

另一个选择:挑战这里需要泛型的假设。例如,它可能只是一个Type实例吗?会:

bool Handle<TModel>(TModel model, Type type)...
...
Handle(model, typeof(MyCommandHandler));
例如

work ?我不能直接回答这个问题,因为我不知道你们的_container.Resolve<TCommandHandler>();方法的细节,关于是否可以调整为Type而不是<T>

c#编译器需要的只是在参数中演示类型,所以不要试图将其放在泛型参数中(在使用站点),而是让您提供一个参数来帮助编译器识别该类型。为了避免混淆,这里有一个例子:

// Your classes/interfaces.
class Container
{
    public static T Resolve<T>()
    {
        Console.WriteLine("Resolving {0}", typeof(T).FullName);
        return default(T);
    }
}
interface ICommandHandler<TModel>
{
    void DoSomething();
}
// An implemented ICommandHandler.
public class WackyCommandHandler : ICommandHandler<string>
{
    public void DoSomething() { }
}
// Used to help the C# compiler identify types.
public static class Identify
{
    public static TypeIdentity<TType> TheType<TType>()
    {
        return null; // You don't actually need an instance.
    }
}
public sealed class TypeIdentity<TType>
{
    private TypeIdentity() { }
}
// Your method
static bool Handle<TCommandHandler, TModel>(TModel model, TypeIdentity<TCommandHandler> handler)
    where TCommandHandler : ICommandHandler<TModel>
{
    var item = Container.Resolve<TCommandHandler>();
    return true;
}
// And the usage site:
var a = "hello";
Handle(a, Identify.TheType<WackyCommandHandler>());
Console.ReadLine();