有没有比这更好的选择来“打开类型"? [英] Is there a better alternative than this to 'switch on type'?
问题描述
看到 C# 不能 switch
类型(我收集的不是作为特殊情况添加的,因为 is
关系意味着不止一个不同的 case
可能适用),有没有更好的方法来模拟除此之外的类型的切换?
Seeing as C# can't switch
on a Type (which I gather wasn't added as a special case because is
relationships mean that more than one distinct case
might apply), is there a better way to simulate switching on type other than this?
void Foo(object o)
{
if (o is A)
{
((A)o).Hop();
}
else if (o is B)
{
((B)o).Skip();
}
else
{
throw new ArgumentException("Unexpected type: " + o.GetType());
}
}
推荐答案
切换类型在 C# 中肯定是缺乏的(更新:在 C#7/VS 2017 中支持切换类型 - 见下面扎卡里耶茨的回答).为了在没有大的 if/else if/else 语句的情况下执行此操作,您需要使用不同的结构.不久前我写了一篇博文,详细介绍了如何构建 TypeSwitch 结构.
Switching on types is definitely lacking in C# (UPDATE: in C#7 / VS 2017 switching on types is supported - see Zachary Yates's answer below). In order to do this without a large if/else if/else statement, you'll need to work with a different structure. I wrote a blog post awhile back detailing how to build a TypeSwitch structure.
https://docs.microsoft.com/archive/blogs/jaredpar/开关类型
简短版本:TypeSwitch 旨在防止冗余转换并提供类似于普通 switch/case 语句的语法.例如,这里是 TypeSwitch 在标准 Windows 窗体事件上的作用
Short version: TypeSwitch is designed to prevent redundant casting and give a syntax that is similar to a normal switch/case statement. For example, here is TypeSwitch in action on a standard Windows form event
TypeSwitch.Do(
sender,
TypeSwitch.Case<Button>(() => textBox1.Text = "Hit a Button"),
TypeSwitch.Case<CheckBox>(x => textBox1.Text = "Checkbox is " + x.Checked),
TypeSwitch.Default(() => textBox1.Text = "Not sure what is hovered over"));
TypeSwitch 的代码实际上非常小,可以轻松地放入您的项目中.
The code for TypeSwitch is actually pretty small and can easily be put into your project.
static class TypeSwitch {
public class CaseInfo {
public bool IsDefault { get; set; }
public Type Target { get; set; }
public Action<object> Action { get; set; }
}
public static void Do(object source, params CaseInfo[] cases) {
var type = source.GetType();
foreach (var entry in cases) {
if (entry.IsDefault || entry.Target.IsAssignableFrom(type)) {
entry.Action(source);
break;
}
}
}
public static CaseInfo Case<T>(Action action) {
return new CaseInfo() {
Action = x => action(),
Target = typeof(T)
};
}
public static CaseInfo Case<T>(Action<T> action) {
return new CaseInfo() {
Action = (x) => action((T)x),
Target = typeof(T)
};
}
public static CaseInfo Default(Action action) {
return new CaseInfo() {
Action = x => action(),
IsDefault = true
};
}
}
这篇关于有没有比这更好的选择来“打开类型"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!