摆脱冗余类型参数

时间:2011-01-03 08:44:45

标签: c#

我有一个泛型类A,另一个类B处理A的实例并包含一些额外的数据。我需要有两个单独的类。 B不能从A继承,因为A有其他衍生物,B需要包含对A的引用。

作为一个简单的例子,我想写的是这个(字典是A,dicthandler是B):

class dicthandler<T> where T : Dictionary<Tk, Tv>

但是它没有编译,我需要指定所有类型参数:

class dicthandler<T, Tk, Tv> where T : Dictionary<Tk, Tv>

但我实际上并不关心Tk和Tv是什么,所以它们完全是冗余的,我只需要T.每当我想创建一个新实例时,我需要为构造函数指定所有类型参数,这会伤害我

显然我需要一些技巧。有什么想法吗?

3 个答案:

答案 0 :(得分:5)

不,没有办法做到这一点。 DictHandler 的任何实例都必须知道T的确切类型,包括TKeyTValue的类型。

如果您实际拥有相关字典的实例,则可以使用类型推断来减少显式指定类型参数的频率。例如:

public static class DictHandler
{
    public static DictHandler<T, TKey, TValue> CreateHandler<T, TKey, TValue>
        (T dictionary1, Dictionary<TKey, TValue> dictionary2)
        where T : Dictionary<TKey, TValue>
    {
        return new DictHandler<T, TKey, TValue>();
    }
}

public class DictHandler<T, TKey, TValue> where T : Dictionary<TKey, TValue>
{
}

然后像这样创建:

Dictionary<string, int> dict = new Dictionary<string, int>();
var handler = DictHandler.CreateHandler(dict, dict);

我相信你必须拥有这两个参数的原因是,参数(在类型推断中使用的所有参数)最终与直接提及类型参数的参数相对应。我不完全确定 - 这肯定有些难看。

另一种方法是为A创建一个基本类型或基本接口,其中不是泛型。例如,在这种情况下(假设我们可以控制字典),我们创建:

public interface INonGenericDictionary
{
    // Members which don't rely on the type parameters
}

public class Dictionary<TKey, TValue> : INonGenericDictionary
{
    ...
}

然后

public class DictHandler<T> where T : INonGenericDictionary
{
    ...
}

我们无法确定这是否适用于您的情况,但可能

答案 1 :(得分:2)

在对象构建方面,当前的C#要求你非常具体。不过,这似乎不太常见,所以你可以从当前类型的类型参数创建一个CreateDictHandler类型:

private dicthandler<T, Tk, Tv> CreateDictHandler() {...}
...
var handler = CreateDictHandler();

如果类型参数用于方法,则必须为构造函数提供它们,但您仍然可以在变量声明中使用var


可能也发现在很多情况下太多泛型实际上是一件坏事。如果它开始变得过于粗糙,有时像IDictionary(非泛型)这样的东西是真正需要的。

答案 2 :(得分:1)

您不能省略键和值类型参数,因为它们是泛型类型签名的一部分。但您考虑过将类型定义更改为此吗?

class dicthandler<TKey, TValue>

然后您可以使用Dictionary<TKey, TValue>类型。很明显,你的类型只能用于字典,所以不需要强制将这种类型作为泛型参数传递,因为你已经知道它是什么。