【问题标题】:Switch over PropertyType切换属性类型
【发布时间】:2008-09-18 10:47:28
【问题描述】:

我怎样才能做到这一点?

switch(property.PropertyType){
    case typeof(Boolean): 
        //doStuff
        break;
    case typeof(String): 
        //doOtherStuff
        break;
    default: break;
}

我不想使用该名称,因为字符串比较类型非常糟糕,并且可能会发生变化。

【问题讨论】:

    标签: c# switch-statement


    【解决方案1】:
            System.Type propertyType = typeof(Boolean);
            System.TypeCode typeCode = Type.GetTypeCode(propertyType);
            switch (typeCode)
            {
                case TypeCode.Boolean:
                    //doStuff
                    break;
                case TypeCode.String:
                    //doOtherStuff
                    break;
                default: break;
            }
    

    您可以对 TypeCode.Object 使用混合方法,如果使用 typeof,您可以在其中动态。这非常快,因为对于第一部分 - 开关 - 编译器可以根据查找表来决定。

    【讨论】:

    • 如果您想比较除简单内置类型以外的任何内容,则将无法使用,因为 TypeCode 是一个枚举,除了简单类型(如 bool、int32 等)之外不包含任何内容...
    • 当然是这样。但是超出了我首先省略的示例的范围。稍后添加以明确这一点。谢谢。
    • 好吧,在我的特殊情况下,它只会是基本类型。
    • 请注意,如果您希望它适用于 Nullable 类型,则必须检查 propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(System.Nullable) 然后获取底层类型...这里是一个例子:yakkowarner.com/2008/12/…
    【解决方案2】:

    你不能。您可以做的是使用字典在类型和委托之间创建映射:

    var TypeMapping = new Dictionary<Type, Action<string>>(){
        {typeof(string), (x)=>Console.WriteLine("string")},
        {typeof(bool), (x)=>Console.WriteLine("bool")}
    };
    
    
    
    string s = "my string";
    
    TypeMapping[s.GetType()]("foo");
    TypeMapping[true.GetType()]("true");
    

    【讨论】:

      【解决方案3】:

      我认为您在这里寻找的是一张好的地图。使用委托和通用 IDictionary 你可以做你想做的事。

      试试这样的:

      private delegate object MyDelegate();
      
      private IDictionary<Type, MyDelegate> functionMap = new IDictionary<Type, MyDelegate>();
      
      public Init()
      {
        functionMap.Add(typeof(String), someFunction);
        functionMap.Add(tyepof(Boolean), someOtherFunction);
      }
      
      public T doStuff<T>(Type someType)
      {
         return (T)functionMap[someType]();
      }
      

      【讨论】:

        【解决方案4】:

        C# 7.0 将支持切换类型作为更大模式匹配功能的一部分。 此示例取自宣布新功能的.NET blog post

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

        【讨论】:

          【解决方案5】:

          不用担心在 switch 中使用字符串,因为如果你有多个,编译器会自动将其转换为哈希查找,尽管它看起来非常棒,但它的性能还不错。

          类型字符串更改的问题可以通过自己进行显式哈希查找并在静态构造函数中填充哈希的内容来解决。这样,哈希在运行时会填充正确的字符串,因此它们保持正确。

          【讨论】:

            【解决方案6】:

            你不能在 c# 中使用 switch 来做到这一点,因为 case 必须保持不变。

            有什么问题:

            if(property.PropertyType == typeof(bool)) {
                //dostuff;
            }
            else if (property.PropertyType == typeof(string)) {
                //do other stuff;
            }
            

            【讨论】:

            • OP 一定已经知道了。不过 +1 以抵消反对票;也是一个有效的解决方案,有时它无法取代内置构造的强大功能。
            【解决方案7】:

            我最近不得不做一些类似的事情,并且不能选择使用 switch。对 typeof(x) 执行 == 很好,但更优雅的方式可能是执行以下操作:

            if(property.PropertyType is bool){
              //dostuff;
            }
            else if (property.PropertyType is string){
                //do other stuff;
            }
            

            但是,我不确定你是否可以这样使用“is”关键字,我认为它只适用于对象......

            【讨论】:

              【解决方案8】:

              关于字符串匹配:问题中的要求之一是不通过字符串匹配进行。

              字典是我将整个序列化算法放在自己的库中时使用的一种方法。 至于现在,我将首先尝试 typeCode,因为我的案例仅使用基本类型。 如果这不起作用,我将回到 if/else 群:S

              在人们问我为什么我想要自己的序列化之前: 1) .net xml 序列化不会序列化没有设置器的属性 2) 序列化必须遵守一些遗留规则

              【讨论】:

              • 您可以通过添加一个空集来绕过属性限制。公共字符串 MyProp{ get{return foo;} set{;}}
              【解决方案9】:

              只需使用普通的 if/else if/else 模式:

              if (property.PropertyType == typeof(Boolean))
              {
              } 
              else if (property.PropertyType == typeof(String))
              {
              }
              else if (...)
              {
              }
              

              【讨论】:

                【解决方案10】:

                我个人最喜欢Dictionary&lt;Type, other&gt; 方法...我什至可以为您提供另一个示例:http://www.timvw.be/presenting-namevaluecollectionhelper/

                如果您坚持编写 switch-case 语句,您可以使用类型名称...

                switch (blah.PropertyType.FullName)
                {
                   case typeof(int).FullName: break;
                   case typeof(string).FullName: break;
                }
                

                【讨论】:

                • @nawfal 我确实赞成这个,因为你错了。它适用于 System.String。 System.String 是不可变类型。
                • @toATwork 是否不可变,case 需要一个常量表达式。例如如果您示例中的 System.String 看起来像 case "myCompileTimeValue": 这将起作用。但如果它看起来像 case myRunTime.Value: 它不会编译。在未来的 C# 版本(可能是 7 版)中,情况可能会发生变化,包括模式匹配等等。
                • @nawfal 你是对的!就我而言,它类似于"someString"。道歉。在评论之前应该考虑一下。每个案例都必须是唯一的,以及如何使用变量/属性来保证这一点......愚蠢的我......
                猜你喜欢
                • 2021-03-28
                • 2016-09-29
                • 1970-01-01
                • 2021-12-20
                • 2013-01-22
                • 2020-10-30
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多