[英]Switch expression on System.Type in C# 8
I'm curious is any other way to write something like this with new switch expression 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)
};
Because _ when type == typeof(string)
looks kinda weird especially when we have type pattern and other very convenient instruments.因为
_ when type == typeof(string)
看起来有点奇怪,尤其是当我们有类型模式和其他非常方便的工具时。
As others have alluded to, you actually need to have an instance of a type available to use the new type-matching features, not the representative System.Type
.正如其他人所暗示的那样,您实际上需要一个类型的实例来使用新的类型匹配功能,而不是代表性的
System.Type
。 If you want to match directly on the type, the way you're doing it seems to be the only viable way for the time being.如果您想直接在类型上进行匹配,那么您这样做的方式似乎是目前唯一可行的方式。
That being said, I would argue in this case that a standard switch
statement might be more readable:话虽如此,在这种情况下,我认为标准
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);
}
If you really want to keep the switch expression, you could potentially get around this by matching on type names instead, though as a commenter pointed out below, this option is particularly brittle and will not work with certain types (such as DateTime?
or Nullable<DateTime>
):如果您真的想保留 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)
};
If you would use generics and use the latest c# version you could do something like this:如果您使用 generics 并使用最新的 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();
}
}
according to your example this would be something along those lines: (can be compiled, but didn't test it at runtime)根据您的示例,这将是类似的内容:(可以编译,但在运行时未对其进行测试)
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)
};
instead of dynamic also object could be used.也可以使用 object 代替动态。
In a similar situation I ended up using a generic helper to make intent clearer.在类似的情况下,我最终使用了一个通用助手来使意图更清晰。 I did have
<T>
type available but not the C#9 default (T) switch { string[] =>...}
syntax.我确实有
<T>
类型可用,但没有 C#9 default (T) switch { string[] =>...}
语法。
This solution seems to be handling nullables like DateTime?
这个解决方案似乎正在处理像
DateTime?
correctly.正确。
static object Convert(string str, Type type)
=> type switch {
_ when Match<string>(type) => str,
_ when Match<string[]>(type) => str.Split(new[] { ',', ';' }),
_ => TypeDescriptor.GetConverter(type).ConvertFromString(str)
};
static bool Match<T>(Type t) => typeof(T) == t;
For my <T>
available case it became something like:对于我的
<T>
可用案例,它变成了这样:
static object Convert<T>(string str)
=> type switch
{
_ when Match<string, T>() => str,
_ when Match<string[], T>() => str.Split(new[] { ',', ';' }),
_ => TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(str)
};
static bool Match<TA, TB>() => typeof(TA) == typeof(TB);
edit : One can shorten the syntax a bit with an extension method:编辑:可以使用扩展方法稍微缩短语法:
...
public static bool Is<T>(this System.Type type) => type == typeof(T);
...
static object Convert(string str, Type type)
=> type switch {
_ when type.Is<string>() => str,
_ when type.Is<string[]>() => str.Split(new[] { ',', ';' }),
_ => TypeDescriptor.GetConverter(type).ConvertFromString(str)
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.