嵌套泛型:重用外部类型参数
本文关键字:外部 类型参数 泛型 嵌套 | 更新日期: 2023-09-27 18:12:27
我正在尝试删除系统集合的重复代码。具有可变数量参数的函数。(这是用来允许代码"挂钩"到其他组件的逻辑。)因此,我试图删除几个几乎相同的方法,并使用泛型方法代替。
为了使其工作,我将它们包装在HookContainer类中,并使其实现一个公共接口。
public interface IHookContainer
{
void Add<TFunc> (string filterName, int priority, KeyValuePair<string, TFunc> action);
}
public class HookContainer<T>:IHookContainer
{
Dictionary<string,OrderedDictionary<string,T>> dict = new Dictionary<string, OrderedDictionary<string, T>> ();
public void Add<T> (string filterName, int priority, KeyValuePair<string, T> action)
{
// Add an item to the Dictionary
}
}
这允许我将它们全部放在一个字典中,我可以使用类型
访问它Dictionary<Type,IHookContainer> containers = new Dictionary<Type, IHookContainer> (){
{
typeof(HookContainer<System.Func<object,object>>),new HookContainer<System.Func<object,object>>()
},
// More dictionary entries like this (with more parameters)
};
public string AddFilter<T> (string filterName, T action, string filterTag = null, int priority=0)
{
KeyValuePair<string, T> data = new KeyValuePair<string, T> (filterTag, action);
if (containers.ContainsKey (typeof(T))) {
IHookContainer container = containers [typeof(T)];
container.Add<T> (filterName, dictPriority, data);
}
return filterTag;
}
现在我得到一个编译错误说:
cannot convert `System.Collections.Generic.KeyValuePair<string,T>'
expression to type `System.Collections.Generic.KeyValuePair<string,T>'
所以它显然缺少一些我认为理所当然的信息。或者我想错了。或两者兼而有之。为什么它不能将一个类型转换为…
如果实现了接口,显然不能为泛型方法使用来自泛型类的相同Type参数。遗憾的是,类型也无法推断。有什么办法能解决这个问题吗?
还有一个警告,类型参数名与外部类型参数名相同。我能告诉编译器这是完全有意的吗?
谢谢你的帮助。我使用的是c# 4.0
更新:
我可以让代码工作,通过声明HookContainer与第二个类型参数,并使用它传递到Add
方法。
现在是这样的:
public class HookContainer<T,U>:IHookContainer
{
Dictionary<string,OrderedDictionary<string,T>> dict = new Dictionary<string, OrderedDictionary<string, T>> ();
public void Add<U> (string filterName, int priority, KeyValuePair<string, T> action)
{
// Add an item to the Dictionary
}
}
这当然要求我在声明Dictionary时冗余地传递两次容器类型:Dictionary<Type,IHookContainer> containers = new Dictionary<Type, IHookContainer> (){
{
typeof(HookContainer<System.Func<object,object>,System.Func<object,object>>),new HookContainer<System.Func<object,object>,System.Func<object,object>>()
}
};
所以虽然这可能有效,但看起来和感觉起来都很荒谬。是否有任何方法可以(重新)使用单个Type参数?
更新
我误解了你的问题。我认为你实现这个的方式,并不是你想要的。接口中的声明与实现中的声明不同。在你的接口声明中,你指定这个接口的实现应该有一个泛型函数(它可以被所有类型调用)。在您的实现中,您希望将其限制为在类中指定的类型。类实现将针对一个特定类型。。IHookContainer
接口指定你可以用int,string等来调用Add
函数。而在HookContainer<string>
中,您只能使用字符串参数调用Add
。
一个更合适的实现,你想要什么,但你不能存储在字典是:
public interface IHookContainer<T>
{
Add(string filterName, int priority, KeyValuePair<string, T> action);
}
解决方案可以是(我可能会做的)是将Dictionary更改为List并创建一个检索正确IHookContainer<T>
的函数。或者,当条目数量很大时,保留你的字典,并按键查找正确的条目。
private List<object> containers = new List<object>();
private IHookContainer<T> GetCorrectHookContainer<T>()
{
// might need to add when not available?
return containers.OfType<IHookContainer<T>>().FirstOrDefault();
}
你的AddFilter
函数将是这样的(伪代码)
public void AddFilter<T>(...)
{
GetCorrectHookContainer<T>().Add(...);
}
老:
因为您在函数中(再次)指定了类型参数,所以类的T
与函数中的T
不同。泛型函数中的T
参数"隐藏"了类的T
。你可以用它。你不必在你的函数中指定它。你的实现可以是:
public void Add(string filterName, int priority, KeyValuePair<string, T> action)
{
// Add an item to the Dictionary
}
使用例子:
var x = new HookContainer<int>();
x.Add("test", 1, new KeyValuePair<string,int>("test", 4));
似乎问题是Add
的TFrom
和HookContainer
的T
是两种不同的通用类型。
我不知道是否可能,但我会使用C的主签名(int argc, char[] argv)
而不是Func
函数:
System.Func<int, object[], object>