C# switch
关于泛型类型参数的声明,i.e<T>
0.下面的代码中使用的演示类型。
class MyClass { }; struct MyStruct { }; enum MyEnum { };
1.在您的项目中全局定义一个struct
具有单个泛型类型参数,如下所示。
public struct TokenOf<X> { };
3. switch
陈述。这个演示展示了一个通用的method,但当然该技术也可以在通用范围内的任何地方使用class
or struct
:(注意这个方法使用开关表达式 https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/switch-expression语法可用于C# 8):
string GenericMethod<T>() =>
default(TokenOf<T>) switch
{
TokenOf<int> _ /**/ => "II",
TokenOf<Guid> _ /**/ => "GG",
TokenOf<string> _ /**/ => "SS",
TokenOf<object> _ /**/ => "OO",
TokenOf<MyEnum> _ /**/ => "EE",
TokenOf<MyClass> _ /**/ => "CC",
TokenOf<MyStruct> _ /**/ => "QQ",
_ /**/ => "??",
};
3a.在这些 switch 表达式示例中,您可以使用{ }
而不是“丢弃符号”_
以获得同等结果。这表明可爱的(或者可能是滥用的)代码格式化选项,例如:
string GenericMethod<T>() => default(TokenOf<T>) switch
{
TokenOf<int> /**/ _ => "II",
TokenOf<Guid> /**/ _ => "GG",
// etc...
TokenOf<MyStruct> /**/ _ => "QQ",
{ /**/ } => "??",
};
4.演示测试代码
void switch_on_generic_type() =>
Console.WriteLine($@"{
GenericMethod<int>()} {
GenericMethod<Guid>()} {
GenericMethod<string>()} {
GenericMethod<object>()} {
GenericMethod<MyEnum>()} {
GenericMethod<MyClass>()} {
GenericMethod<MyStruct>()} {
GenericMethod<double>()}");
}
5.演示的输出
II GG SS OO EE CC QQ ??
6.讨论
该技术利用了 .NET 值类型永远无法实例化这一事实。由此可见,值类型(与引用类型不同——例如,它会失去它们的值)System.Type
身份如果null
存储在未指定的变量中)永远不会丢失其特定身份。因此,TokenOf<>
struct 保证代表不同的System.Type
每个不同参数化的身份X
,即使所有实例始终都是“默认”实例(实际上大小为 1 字节)。的泛型类型参数struct
区分它们是必要且充分的。
为了清楚起见,请注意,虽然TokenOf<>
所以must be a struct
,切换后的泛型类型参数<X>
可以是任何有效的 .NET 类型。而事实上,如果X
保证代表一个值类型,你甚至不需要TokenOf<>
根本没有包装。例如,考虑带有类型参数的泛型类或方法T
受限于unmanaged
(or struct
) 关键字。在这种情况下,上面的 (3.) 等示例将简化为:
string GenericMethod<T>() where T : unmanaged =>
default(T) switch
{
int _ /**/ => "II",
Guid _ /**/ => "GG",
MyEnum _ /**/ => "EE",
MyStruct _ /**/ => "QQ",
TimeSpan _ /**/ => "TS",
_ /**/ => "??",
};
The typeof(T)
运算符在本页的其他答案中使用,但因为它(根据定义)体现了具体化 https://en.wikipedia.org/wiki/Reification_(computer_science)#Reflective_programming_languages操作于T
这对于静态分析来说本质上是不透明的,并且在本质上是被硬阻止的System.Type https://learn.microsoft.com/en-us/dotnet/api/system.type?view=netframework-4.8实例(显然,它本身只能在运行时存在)我认为它是一个非常生硬和戏剧性的工具。
通过避免typeof
,这里展示的技术可能对编译器、优化器、分析器和其他工具更友好CTS https://en.wikipedia.org/wiki/Common_Type_System 离线元数据 https://en.wikipedia.org/wiki/Metadata_(CLI)系统(待调查)。最重要的是,习惯国际法制度放宽了过度强制的规定System.Type
实例化(通过typeof
)可能对 JIT 有利。