这里OP提出的问题是,当您没有实际的类型可用,而只有其假定的System.Type时,您无法使用新的C# 7基于类型的switch功能。
接受的答案总结如下,对于精确类型匹配效果很好(这里显示了一点改进,但请参见下面的最终示例以获得更进一步的简化)...
Type type = ...
switch (type)
{
case Type _ when type == typeof(Int32):
case Type _ when type == typeof(Decimal):
this.value = Math.Max(Math.Min(this.value, Maximum), Minimum);
break;
}
需要注意的重要一点是,对于派生的引用类型层次结构,这将不会展示与使用"is"关键字进行匹配的"if...else"链相同的行为。请考虑:
class TBase { }
class TDerived1 : TBase { }
class TDerived2 : TBase { }
sealed class TDerived3 : TDerived2 { }
TBase inst = ...
if (inst is TDerived1)
{
}
else if (inst is TDerived2)
{
}
else if (inst is TDerived3)
{
}
由于`TDerived3`是`TDerived2`的一种,当使用`is`匹配时,两种情况都由第二个分支处理。由于在此示例中`TDerived3`被标记为“sealed”,因此没有实例能够匹配第三个分支。
这突显了运行时“严格”或“精确”的类型相等与更微妙的
“类型包容性”(类型“兼容性”)之间的差异。由于OP问题中的类型是`ValueType`原始类型(无法派生自其他类型),所以这种差异并不重要。但是,如果我们将接受的答案中的“精确类型匹配”与上面显示的示例类结合起来,我们将得到不同的结果。
Type type = ...
switch (type)
{
case Type _ when type == typeof(TDerived1):
// Handles case TDerived1
break;
case Type _ when type == typeof(TDerived2):
// Handles case TDerived2
break;
case Type _ when type == typeof(TDerived3):
// Handles case TDerived3 <--- !
break;
}
实际上,
C# 7甚至不会编译与之前显示的
if / else
序列相对应的
switch
语句。(注:看起来编译器应该将此视为警告,而不是错误,因为无害的结果只是一段无法访问的代码分支,这是编译器在其他地方视为警告的条件,并且还考虑到编译器在
if / else
版本中甚至根本不检测到看似相同的情况)。这是代码示例:
![enter image description here](https://istack.dev59.com/2shFx.webp)
无论如何,哪种替代行为是合适的,或者是否重要,都取决于您的应用程序,所以我在这里的观点只是为了引起注意。如果您确定需要更精明的“类型兼容性”版本的开关方法,以下是如何操作的:
Type type = ...
switch (type)
{
case Type _ when typeof(TDerived1).IsAssignableFrom(type):
break;
case Type _ when typeof(TDerived2).IsAssignableFrom(type):
break;
case Type _ when typeof(TDerived3).IsAssignableFrom(type):
break;
}
和之前一样,第三个案例是多余的,因为对于当前示例,TDerived3
是密封的。
最后,正如我在本页面的另一个answer中提到的,你甚至可以进一步简化对switch
语句的使用。由于我们只使用了when
子句的功能,并且由于我们可能仍然在一个变量中拥有原始的被切换的Type
实例,所以在switch
语句中不需要提及该变量,也不需要在每个case
中重复其类型(在这种情况下为Type
)。只需执行以下操作:
Type type = ...
switch (true)
{
case true when typeof(TDerived1).IsAssignableFrom(type):
break;
case true when typeof(TDerived2).IsAssignableFrom(type):
break;
case true when typeof(TDerived3).IsAssignableFrom(type):
break;
}
注意到
switch(true)
和
case(true)
。我建议在仅依赖
when
子句(即除了在此处讨论的基于
System.Type
的情况之外)时使用这种更简单的技术。
Dictionary<Type, Action>
,以调用特定类型的函数,而不是使用开关语句。我认为这样编写代码更加简洁。 - xxbbccSystem.Type
上进行切换,而不是直接在值上进行切换?我猜在此之前可能需要使用typeof(value)
。 - Matthias247