双泛型函数的语法糖
本文关键字:语法 函数 泛型 | 更新日期: 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();