我想做一个像下面这样的功能。 K
和L
是通用类型参数。 (它是MultiKeyDictionary by Aron Weiler的自定义,万一你想知道)
protected void Dissociate(K primaryKey, L subKey)
{
primaryToSubkeyMapping.Remove(primaryKey??subDictionary[subKey]);
subDictionary.Remove(subKey??primaryToSubkeyMapping[primaryKey]);
}
每个参数都是可选的,但至少需要一个参数; null
表示缺席。问题是,如果泛型参数是值类型,我需要用Nullable
包含函数的参数,以便primaryKey??
有效和所以我可以通过null
指定参数的缺席。但是,如果Nullable<K>
是引用类型,K
也是无效的!
那么,我可以以某种方式编写实现,以便它对两种情况都有效吗?
答案 0 :(得分:0)
Botton line:此可以完成,但需要不成比例的开销。所以这完全是不切实际的。
最后,我通过添加两个没有参数的重载方法来解决这个问题。
根据C# specification v.3.0,§B.2.7,类型约束也可以放在单个方法上。但是,这些方法需要将约束的类型放在上作为它们自己的类型参数。所以,我能够做到这样的伎俩:
protected void Dissociate<KP,LP>(KP? primaryKey, LP? subKey)
where KP:struct,K where LP:struct,L
{
primaryToSubkeyMapping.Remove(primaryKey??subDictionary[subKey.Value]);
subDictionary.Remove(subKey??primaryToSubkeyMapping[primaryKey.Value]);
}
但是,现在,我需要为class
和struct
的每个组合制作四个实现!当我尝试在typeof(K).IsValueType
内部调用它们时 - 类似检查,编译器无法将其作为重载解析的提示并产生相应的错误。以不同方式命名它们只是更进一步:编译器不相信在任何具体实现中只会调用其中一个并且仍然无法进行参数类型检查。现在,有两种选择:
通过反思调用相关实现。获取GetMethod()
的泛型类型参数对象,然后制作一个具体的方法将成为一个PINA - 即使我通过不同地命名四个实现来简化前一步骤;
创建四个派生类,每个类具有不同的名称。这会搞砸类层次结构。
简而言之,这种方式完全无法使用。
答案 1 :(得分:0)
您可以指定Nullable<T>
作为参数类型以允许重载。例如:
class A { }
struct B { }
class Program
{
static void Main(string[] args)
{
A a = new A();
B? b = new B();
Method(a);
Method(b);
a = null;
b = null;
Method(a);
Method(b);
}
static void Method<T>(T t) where T : class
{
Console.WriteLine("Reference type: " + (t != null ? "not " : "") + "null");
}
static void Method<T>(Nullable<T> t) where T : struct
{
Console.WriteLine("Nullable<T> type: " + (t != null ? "not " : "") + "null");
}
}
在您自己的情况下,如果类型参数K
和L
可以独立为引用类型或Nullable<T>
,那么您需要四次重载,以便处理所有可能的组合。
您应该能够让所有四个重载共享一个共同的实现,方法是在每个重载中处理null测试,然后调用一个不关心空值的共享实现方法(即可以安全地假设它们是'#ve;已经解决了。)