有没有比这更好的替代“开启类型”?

看到C#无法切换类型(我收集的类型并未作为特例添加,因为是 - 关系表示可能会应用多个不同的情况 ),有没有更好的方法来模拟类型切换?

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结构。

http://blogs.msdn.com/jaredpar/archive/2008/05/16/switching-on-types.aspx

简短版本:TypeSwitch旨在防止冗余转换,并提供类似于正常开关/情况语句的语法。 例如,这里是TypeSwitch在标准Windows窗体事件上的实际操作

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的代码实际上很小,可以很容易地放到你的项目中。

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
        };
    }
}

使用Visual Studio 2017(发行版15. *)附带的C#7,您可以在case语句中使用Types(模式匹配):

switch(shape)
{
    case Circle c:
        WriteLine($"circle with radius {c.Radius}");
        break;
    case Rectangle s when (s.Length == s.Height):
        WriteLine($"{s.Length} x {s.Height} square");
        break;
    case Rectangle r:
        WriteLine($"{r.Length} x {r.Height} rectangle");
        break;
    default:
        WriteLine("<unknown shape>");
        break;
    case null:
        throw new ArgumentNullException(nameof(shape));
}

在C#6中,您可以使用带有nameof()运算符的开关语句(谢谢@Joey Adams):

switch(o.GetType().Name) {
    case nameof(AType):
        break;
    case nameof(BType):
        break;
}

使用C#5及更早版本,您可以使用switch语句,但是您必须使用包含类型名称的魔术字符串......这不是特别重构的(谢谢@ nukefusion)

switch(o.GetType().Name) {
  case "AType":
    break;
}

一种选择是从TypeAction (或其他一些代理)中有一个字典。 根据类型查找动作,然后执行它。 我之前已经将这个用于工厂。

链接地址: http://www.djcxy.com/p/84279.html

上一篇: Is there a better alternative than this to 'switch on type'?

下一篇: Reassign global NSString pointer