C# 开关类型
C# switch with types
编辑:
我有以下代码检查给定的 PropertyInfo
的 type
。
PropertyInfo prop;
// init prop, etc...
if (typeof(String).IsAssignableFrom(prop.PropertyType)) {
// ...
}
else if (typeof(Int32).IsAssignableFrom(prop.PropertyType)) {
// ...
}
else if (typeof(DateTime).IsAssignableFrom(prop.PropertyType)) {
// ...
}
有没有办法在这种情况下使用 switch
语句?这是我目前的解决方案:
switch (prop.PropertyType.ToString()) {
case "System.String":
// ...
break;
case "System.Int32":
// ...
break;
case "System.DateTime":
// ...
break;
default:
// ...
break;
}
我认为这不是最佳解决方案,因为现在我必须给出给定 type
的完全限定 String
值。有什么建议吗?
没有通用的方法,但更常见的是,那些分支包含非常相似的代码。几乎总是对我有用的一种模式是使用字典;
var myIndex = new Dictionary<Type, string> {
{ typeof(string), "some text" },
{ typeof(int), "a whole number" },
{ typeof(decimal), "a fraction" },
};
string description;
if (myIndex.TryGetValue(prop.PropertyType, out description)) {
Console.WriteLine("This type is " + description);
} else {
// 'default'
}
我就如实回答:没办法。
从 C# 6 开始,switch
仅支持精确匹配某些类型的常量。您不是要匹配常量。您多次调用 IsAssignableFrom
方法。
请注意,IsAssignableFrom
不 与完全匹配的类型相同。因此,任何基于相等比较或哈希表的解决方案都行不通。
我认为您的 if ... else if
解决方案完全没问题。
使用您拥有的 ToString 方法,而不是文字值使用 case typeof(string).Name(如果可能的话)现在我面前没有 vs。
首先,在继承类型的情况下,IsAssignableFrom
比仅进行字符串比较要好。
例如 typeof(TextReader).IsAssignableFrom(typeof(StreamReader))
将是 true
,因为 StreamReader
继承自 TextReader
,也适用于接口。
如果只需要直接比较,我可以建议创建Dictionary<Type,Action<PropertyInfo>>
,例如:
var typeSelector = new Dictionary<Type, Action<PropertyInfo>>()
{
{typeof(int), IntAction }
{typeof(string), StringAction }
{typeof(DateTime), DateTimeAction }
};
那么你可以这样使用它:
Action<PropertyInfo> action;
if (typeSelector.TryGetValue(prop.PropertyType, out action))
action(prop);
else
throw new InvalidDataException("Unsupported type");
当然,在这种情况下,您必须为每种类型创建方法,或者在创建字典期间编写代码。
现在在 C# 7.0 中可用。
这个解决方案是针对我原来的问题; switch
语句适用于 PropertyInfo
的 value
而不是其 PropertyType
:
PropertyInfo prop;
// init prop, etc...
var value = prop.GetValue(null);
switch (value)
{
case string s:
// ...
break;
case int i:
// ...
break;
case DateTime d:
// ...
break;
default:
// ...
break;
}
稍微通用一点的答案:
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));
}
Reference:
https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/
如 Mårten Wikström 的回答所示:“How to use switch-case on a Type?”您可以这样使用 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...
}
编辑:
我有以下代码检查给定的 PropertyInfo
的 type
。
PropertyInfo prop;
// init prop, etc...
if (typeof(String).IsAssignableFrom(prop.PropertyType)) {
// ...
}
else if (typeof(Int32).IsAssignableFrom(prop.PropertyType)) {
// ...
}
else if (typeof(DateTime).IsAssignableFrom(prop.PropertyType)) {
// ...
}
有没有办法在这种情况下使用 switch
语句?这是我目前的解决方案:
switch (prop.PropertyType.ToString()) {
case "System.String":
// ...
break;
case "System.Int32":
// ...
break;
case "System.DateTime":
// ...
break;
default:
// ...
break;
}
我认为这不是最佳解决方案,因为现在我必须给出给定 type
的完全限定 String
值。有什么建议吗?
没有通用的方法,但更常见的是,那些分支包含非常相似的代码。几乎总是对我有用的一种模式是使用字典;
var myIndex = new Dictionary<Type, string> {
{ typeof(string), "some text" },
{ typeof(int), "a whole number" },
{ typeof(decimal), "a fraction" },
};
string description;
if (myIndex.TryGetValue(prop.PropertyType, out description)) {
Console.WriteLine("This type is " + description);
} else {
// 'default'
}
我就如实回答:没办法。
从 C# 6 开始,switch
仅支持精确匹配某些类型的常量。您不是要匹配常量。您多次调用 IsAssignableFrom
方法。
请注意,IsAssignableFrom
不 与完全匹配的类型相同。因此,任何基于相等比较或哈希表的解决方案都行不通。
我认为您的 if ... else if
解决方案完全没问题。
使用您拥有的 ToString 方法,而不是文字值使用 case typeof(string).Name(如果可能的话)现在我面前没有 vs。
首先,在继承类型的情况下,IsAssignableFrom
比仅进行字符串比较要好。
例如 typeof(TextReader).IsAssignableFrom(typeof(StreamReader))
将是 true
,因为 StreamReader
继承自 TextReader
,也适用于接口。
如果只需要直接比较,我可以建议创建Dictionary<Type,Action<PropertyInfo>>
,例如:
var typeSelector = new Dictionary<Type, Action<PropertyInfo>>()
{
{typeof(int), IntAction }
{typeof(string), StringAction }
{typeof(DateTime), DateTimeAction }
};
那么你可以这样使用它:
Action<PropertyInfo> action;
if (typeSelector.TryGetValue(prop.PropertyType, out action))
action(prop);
else
throw new InvalidDataException("Unsupported type");
当然,在这种情况下,您必须为每种类型创建方法,或者在创建字典期间编写代码。
现在在 C# 7.0 中可用。
这个解决方案是针对我原来的问题; switch
语句适用于 PropertyInfo
的 value
而不是其 PropertyType
:
PropertyInfo prop;
// init prop, etc...
var value = prop.GetValue(null);
switch (value)
{
case string s:
// ...
break;
case int i:
// ...
break;
case DateTime d:
// ...
break;
default:
// ...
break;
}
稍微通用一点的答案:
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));
}
Reference: https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/
如 Mårten Wikström 的回答所示:“How to use switch-case on a Type?”您可以这样使用 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...
}