如何在Type上使用switch-case?

18 c#

可能重复:
"开启类型"有比这更好的选择吗?

我需要迭代我的类的所有属性,并检查我的类型int是否需要做什么,如果它的字符串..然后做一些事情.我需要使用开关盒.这里我以下面的方式使用switch,但它要求一些常量.看下面的代码:

 public static bool ValidateProperties(object o)
{
    if(o !=null)
    {
        var sourceType = o.GetType();
        var properties = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Static);
        foreach (var property in properties)
        {
            var type = property.GetType();
            switch (type)
            {
                *case typeof(int):* getting error here
                    // d
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

另外我想知道,我应该使用什么检查,typeof(int)或typeof(Int32)?

Mår*_*röm 45

您不能使用开关块来测试类型的值Type.编译代码应该会给出一个错误,例如:

switch表达式或case标签必须是bool,char,string,integral,enum或相应的可空类型

你需要使用if- else语句.

另外:typeof(int)typeof(Int32)等同的.int是一个关键字,Int32是类型名称.

UPDATE

如果您希望大多数类型都是内在类型,则可以通过使用开关块来提高性能Type.GetTypeCode(...).

例如:

switch (Type.GetTypeCode(type))
{
    case TypeCode.Int32:
        // It's an int
        break;

    case TypeCode.String:
        // It's a string
        break;

    // Other type code cases here...

    default:
        // Fallback to using if-else statements...
        if (type == typeof(MyCoolType))
        {
            // ...
        }
        else if (type == typeof(MyOtherType))
        {
            // ...
        } // etc...
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*Jon 11

一个好的,可扩展的方法是根据你想要对那个类型的值做什么,制作一个适当类型的类型和委托的字典.

例如:

var typeProcessorMap = new Dictionary<Type, Delegate>
{
    { typeof(int), new Action<int>(i => { /* do something with i */ }) },
    { typeof(string), new Action<string>(s => { /* do something with s */ }) },
};
Run Code Online (Sandbox Code Playgroud)

然后:

void ValidateProperties(object o)
{
    var t = o.GetType();
    typeProcessorMap[t].DynamicInvoke(o); // invoke appropriate delegate
}
Run Code Online (Sandbox Code Playgroud)

此解决方案是可扩展的,即使在运行时也是可配置的,只要您保持typeProcessorMap正确匹配的密钥和委托值类型也是类型安全的.

看到它在行动.


Die*_*hon 5

通常,最简单的解决方案是打开类型名称:

switch (type.Name)
{
    case "Int32":
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • @Diego,单元测试**不是**类型安全的替代品。 (9认同)
  • IMO,牺牲类型安全是不值得的。毕竟,if/else 链几乎同样简洁,并且具有在编译时捕获拼写错误(更重要的是 - 未来的重构)的优点。 (7认同)

Kir*_*oll 5

这个“答案”是对乔恩答案的详尽阐述。(标记CW)

记录下来,DynamicInvoke有点慢。为了说明这一点,请考虑以下程序:

void Main()
{
    Func<int, string> myFunc = i => i.ToString();
    myFunc.DynamicInvoke(1);   // Invoke once so initial run costs are not considered
    myFunc(1);

    Stopwatch stopwatch = new Stopwatch();

    stopwatch.Start();
    for (int i = 0; i < 1000000; i++)
        myFunc.DynamicInvoke(1);
    stopwatch.Stop();

    var elapsed = stopwatch.Elapsed;

    stopwatch.Restart();
    for (int i = 0; i < 1000000; i++)
        myFunc(1);
    stopwatch.Stop();

    var elapsed2 = stopwatch.Elapsed;

    Console.WriteLine("DynamicInvoke: " + elapsed);
    Console.WriteLine("Direct Invocation: " + elapsed2);
}
Run Code Online (Sandbox Code Playgroud)

打印输出:

DynamicInvoke:00:00:03.1959900
直接调用:00:00:00.0735220

这意味着DynamicInvoke(在这种简单情况下)比直接调用慢42倍。