在 C# 8 中 System.Type 上切换表达式

Switch expression on System.Type in C# 8

我很好奇是否还有其他方法可以在 C# 8 中用新的 switch 表达式编写类似的东西?

public static object Convert(string str, Type type) =>
    type switch
    {
        _ when type == typeof(string) => str,
        _ when type == typeof(string[]) => str.Split(new[] { ',', ';' }),
        _ => TypeDescriptor.GetConverter(type).ConvertFromString(str)
    };

因为 _ when type == typeof(string) 看起来有点奇怪,尤其是当我们有 type pattern 和其他非常方便的工具时。

正如其他人所暗示的,您实际上需要有一个类型的 实例 才能使用新的类型匹配功能,而不是代表 System.Type。如果你想直接在类型上匹配,你这样做的方式似乎是目前唯一可行的方式。

话虽这么说,但在这种情况下,我认为标准 switch 语句可能更具可读性:

switch (type)
{
    case Type _ when type == typeof(string):
        return str;

    case Type _ when type == typeof(string[]):
        return str.Split(',', ';');

    default:
        return TypeDescriptor.GetConverter(type).ConvertFromString(str);
}

如果您真的想要保留 switch 表达式,您可以通过匹配类型名称来解决这个问题,尽管正如下面评论者指出的那样,这个选项特别有用脆弱,不适用于某些类型(例如 DateTime?Nullable<DateTime>):

public static object Convert(string str, Type type) =>
    type.Name switch
    {
        nameof(string) => str,
        nameof(string[]) => str.Split(new[] { ',', ';' }),
        _ => TypeDescriptor.GetConverter(type).ConvertFromString(str)
    };

如果您要使用泛型并使用最新的 c# 版本,您可以这样做:


public partial class DateMultiSelect<TDate> where TDate: struct
{
    protected override void OnParametersSet()
    {
        if(default(TDate) switch 
        {
            DateOnly => true,
            DateTime => true,
            DateTimeOffset => true,
            _ => false
        })
            throw new ArgumentException($"TDate must be a date type, but is {typeof(TDate).Name}");

        base.OnParametersSet();
    }
}

根据你的例子,这应该是这样的: (可以编译,但是运行时没测试)

public static T? Convert<T>(string? str) =>
        default(T) switch
        {
            string => (T?)(dynamic?)str,
            string[] => (T?)(dynamic?)str?.Split(new[] { ',', ';' }),
            _ => (T?)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(str)
        };

也可以使用对象来代替动态。