嵌套泛型:重用外部类型参数

本文关键字:外部 类型参数 泛型 嵌套 | 更新日期: 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)); 

似乎问题是AddTFromHookContainerT是两种不同的通用类型。

我不知道是否可能,但我会使用C的主签名(int argc, char[] argv)而不是Func函数:

System.Func<int, object[], object>