难道还有比这更好的替代品“的类型开关”? [英] Is there a better alternative than this to 'switch on type'?

查看:156
本文介绍了难道还有比这更好的替代品“的类型开关”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看到,因为C#不能开关在类型(我猜没有添加作为一个特殊的情况,因为is-a的关系意味着多个不同的情况可能适用),是否有更好的方法来模拟式开关比这个?

 无效美孚(对象o)
{
    如果(O是A)
    {
        ((A)O).Hop();
    }
    否则,如果(o为B)
    {
        ((B)O).Skip();
    }
    其他
    {
        抛出新的ArgumentException(意外的类型:+ o.GetType());
    }
}


解决方案

开机类型肯定是在C#中缺乏。为了做到这一点没有一个大的if / else if / else语句,你需要具有不同结构的工作。我写了一篇博客一段时间回来,详细说明如何建立一个TypeSwitch结构。

<一个href=\"http://blogs.msdn.com/jaredpar/archive/2008/05/16/switching-on-types.aspx\">http://blogs.msdn.com/jaredpar/archive/2008/05/16/switching-on-types.aspx

短版:TypeSwitch设计为prevent冗余铸造并给予了语法类似于普通的开关/ case语句。例如,这里是TypeSwitch在行动上一个标准的Windows窗体事件

  TypeSwitch.Do(
    发件人,
    TypeSwitch.Case&LT;按钮和GT;(()=&GT; textBox1.Text =打一键),
    TypeSwitch.Case&LT;&复选框GT;(X =&GT; textBox1.Text =复选框+ x.Checked)
    TypeSwitch.Default(()=&GT; textBox1.Text =不知道什么悬停));

在code为TypeSwitch实际上是pretty小,可以很容易地放入您的项目。

 静态类TypeSwitch {
    公共类CaseInfo {
        公共BOOL ISDEFAULT {搞定;组; }
        公共类型目标{搞定;组; }
        公共动作&LT;对象&gt;行动{搞定;组; }
    }    公共静态无效DO(对象源,则params CaseInfo []例){
        VAR类型= source.GetType();
        的foreach(在案件进入VAR){
            如果(entry.IsDefault || entry.Target.IsAssignableFrom(类型)){
                entry.Action(源);
                打破;
            }
        }
    }    公共静态CaseInfo案例&LT; T&GT;(行动行动){
        返回新CaseInfo(){
            行动= X =&GT;行动(),
            目标= typeof运算(T)
        };
    }    公共静态CaseInfo案例&LT; T&GT;(动作&LT; T&GT;动作){
        返回新CaseInfo(){
            行动=(X)=&GT;操作((T)X)
            目标= typeof运算(T)
        };
    }    公共静态CaseInfo默认(行动行动){
        返回新CaseInfo(){
            行动= X =&GT;行动(),
            ISDEFAULT =真
        };
    }
}

Seeing as C# can't switch on a Type (which I gather wasn't added as a special case because is-a relationships mean that more than one distinct case might apply), is there a better way to simulate switching on type 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());
    }
}

解决方案

Switching on types is definitely lacking in C#. 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.

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

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"));

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆