C# 消除冗余类型参数

C# 消除冗余类型参数,c#,C#,我有一个通用类a,另一个类B处理a的实例并包含一些附加数据。我需要两个独立的班级。B不能从A继承,因为A有其他派生,B需要包含对A的引用 作为一个简单的例子,我想写的是(dictionary是a,dicthandler是B): 类dicthandler,其中T:Dictionary 但它无法编译,我需要指定所有类型参数: class dicthandler<T, Tk, Tv> where T : Dictionary<Tk, Tv> private dicthand

我有一个通用类a,另一个类B处理a的实例并包含一些附加数据。我需要两个独立的班级。B不能从A继承,因为A有其他派生,B需要包含对A的引用

作为一个简单的例子,我想写的是(dictionary是a,dicthandler是B):

类dicthandler,其中T:Dictionary
但它无法编译,我需要指定所有类型参数:

class dicthandler<T, Tk, Tv> where T : Dictionary<Tk, Tv>
private dicthandler<T, Tk, Tv> CreateDictHandler() {...}
...
var handler = CreateDictHandler();
类dicthandler,其中T:Dictionary
但我实际上并不关心Tk和Tv是什么,所以它们是完全冗余的,我只需要t。每当我想创建一个新实例时,我需要为构造函数指定所有类型参数,这对我来说很不利


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

没有,没有办法。
DictHandler
的任何实例都必须知道
T
的确切类型,包括
TKey
TValue
的类型

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

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>
{
}
公共静态类DictHandler
{
公共静态DictHandler CreateHandler
(T字典1,字典2)
T:字典在哪里
{
返回新的DictHandler();
}
}
公共类DictHandler,其中T:Dictionary
{
}
然后像这样创建它:

Dictionary<string, int> dict = new Dictionary<string, int>();
var handler = DictHandler.CreateHandler(dict, dict);
Dictionary dict=new Dictionary();
var handler=DictHandler.CreateHandler(dict,dict);
我相信您必须拥有这两个参数的原因是,参数(在类型推断中使用的所有参数)最终与直接提到类型参数的参数相对应。但我不完全确定——这确实有点难看

另一种选择是为非泛型的创建基类型或基接口。例如,在这种情况下(假设我们可以控制字典),我们将创建:

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

public class Dictionary<TKey, TValue> : INonGenericDictionary
{
    ...
}
NGenericDictionary中的公共接口 { //不依赖类型参数的成员 } 公共类词典:INonGenericDictionary { ... } 然后

公共类DictHandler,其中T:INonGenericDictionary
{
...
}

我们无法确定这是否适合您的情况,但它可能是。

当涉及到对象构造时,当前的C#要求您非常具体。但是,这似乎不太可能经常创建,因此您可以从当前类型的类型参数创建
CreateDictHandler
类型:

class dicthandler<T, Tk, Tv> where T : Dictionary<Tk, Tv>
private dicthandler<T, Tk, Tv> CreateDictHandler() {...}
...
var handler = CreateDictHandler();
private dicthandler CreateDictHandler(){…}
...
var handler=CreateDictHandler();
如果类型参数用于方法,则必须为构造函数提供它们,但仍然可以在变量声明中使用
var



您可能还会发现,在许多情况下,过多的泛型实际上是一件坏事。如果它开始变得过于粗糙,有时像
IDictionary
(非泛型)这样的东西确实是可取的。

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

class dicthandler<TKey, TValue>
类处理程序

然后您可以只使用类型
字典
。很明显,您的类型将仅用于字典,因此不需要强制将此类型作为泛型参数传递,因为您已经知道它是什么。

这不起作用,因为a可以有派生,我不知道这是一本词典还是从中派生出来的其他东西。@fejesjoco:那么使用
IDictionary
?或者特定的类型对你的类来说很重要吗?扩展方法是个好主意,但遗憾的是,它不起作用。请看,“…无法推断…”@fejesjoco:这不是一个扩展方法-只是一个静态方法。但我明白你的意思。隐马尔可夫模型。。。看看我能做些什么…@fejesjoco:好吧,我已经让一个粗俗的黑客帮我工作了。但这还远远不够理想——如果你能使用第二种方法,那会更好。我考虑过非泛型。但处理程序的某些方法需要另一个字典作为参数(例如,比较或合并)。在这种情况下,您可以传递给它的实际字典没有编译时限制,就像您不能给处理程序一样,我需要运行时检查。@fejesjoco:如果他们要使用另一个字典,那么您确实需要知道类型参数,以确保参数具有相同的编译时类型。您最初声称不关心
Tk
Tv
是不正确的。它们可能是任意类型,但您显然需要能够在其他地方引用它们。