Is there a better alternative than this to 'switch on type'?

后端 未结 30 2850
梦毁少年i
梦毁少年i 2020-11-22 03:28

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

30条回答
  •  野性不改
    2020-11-22 04:09

    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/switching-on-types

    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

    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 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(Action action) {
            return new CaseInfo() {
                Action = x => action(),
                Target = typeof(T)
            };
        }
    
        public static CaseInfo Case(Action 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
            };
        }
    }
    
        

    提交回复
    热议问题