[英]C# switch with types
EDIT: This is now available in C# 7.0. 编辑: 现在可以在C#7.0中使用。
I have the following piece of code that checks a given PropertyInfo
's type
. 我有以下代码检查给定的
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)) {
// ...
}
Is there a way to use a switch
statement in this scenario? 有没有办法在这种情况下使用
switch
语句? This is my current solution: 这是我目前的解决方案:
switch (prop.PropertyType.ToString()) {
case "System.String":
// ...
break;
case "System.Int32":
// ...
break;
case "System.DateTime":
// ...
break;
default:
// ...
break;
}
I don't think this is the best solution, because now I have to give the fully qualified String
value of the given type
. 我不认为这是最好的解决方案,因为现在我必须给出给定
type
的完全限定的String
值。 Any tips? 有小费吗?
This is now available in C# 7.0. 现在可以在C#7.0中使用它。
This solution is for my original question; 这个解决方案适合我原来的问题;
switch
statements work on the value
of the PropertyInfo
and not its PropertyType
: 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;
}
Slightly more generic answer: 稍微更通用的答案:
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/
参考: https : //blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/
I'll answer the question exactly as asked: There is no way. 我将完全按照要求回答这个问题:没有办法。
switch
as of C# 6 only supports matching constants of certain types exactly. 从C#6
switch
只支持精确匹配某些类型的常量。 You are not trying to match constants. 你不是试图匹配常数。 You are invoking the
IsAssignableFrom
method many times. 您多次调用
IsAssignableFrom
方法。
Note, that IsAssignableFrom
is not identical to matching types exactly. 注意,
IsAssignableFrom
是不相同的精确匹配的类型。 Therefore, any solution based on equality comparisons or hash tables can't work. 因此,任何基于相等比较或哈希表的解决方案都无法工作。
I think the if ... else if
solution that you have is totally fine. 我认为
if ... else if
你拥有的解决方案完全没问题。
There's no general way, but more often that not, those branches contain very similar code. 没有通用的方法,但更常见的是,这些分支包含非常相似的代码。 One pattern that almost always works for me is to use a dictionary;
几乎总是对我有用的一种模式是使用字典;
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'
}
使用你拥有的ToString方法,但不是文字值使用case typeof(string).Name(如果可能的话)现在没有vs在我面前。
First of all IsAssignableFrom
is better then just string comparing in case of inherited types. 首先,
IsAssignableFrom
比继承类型的字符串比较更好。 For example typeof(TextReader).IsAssignableFrom(typeof(StreamReader))
will be true
, because StreamReader
inherited from TextReader
, also work's for interfaces. 例如
typeof(TextReader).IsAssignableFrom(typeof(StreamReader))
将为true
,因为StreamReader
继承自TextReader
,也适用于接口。
If you need only direct comparison, I can suggest create Dictionary<Type,Action<PropertyInfo>>
, for example: 如果您只需要直接比较,我可以建议创建
Dictionary<Type,Action<PropertyInfo>>
,例如:
var typeSelector = new Dictionary<Type, Action<PropertyInfo>>()
{
{typeof(int), IntAction }
{typeof(string), StringAction }
{typeof(DateTime), DateTimeAction }
};
Then you can use it like this: 然后你可以像这样使用它:
Action<PropertyInfo> action;
if (typeSelector.TryGetValue(prop.PropertyType, out action))
action(prop);
else
throw new InvalidDataException("Unsupported type");
Sure in this case you will have to create method for each type, or write code during creation of dictionary. 在这种情况下,您必须为每种类型创建方法,或在创建字典期间编写代码。
As shown in Mårten Wikström's answer: " How to use switch-case on a Type? " you can use Type.GetTypeCode
as such: 如MårtenWikström的回答所示:“ 如何在Type上使用switch-case? ”你可以使用
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...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.