Reputation: 6541
EDIT: This is now available in C# 7.0.
I have the following piece of code that checks a given PropertyInfo
's 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? 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
. Any tips?
Upvotes: 8
Views: 6530
Reputation: 665
As shown in Mårten Wikström's answer: "How to use switch-case on a Type?" you can use Type.GetTypeCode
as such:
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...
}
Upvotes: 0
Reputation: 6541
This is now available in C# 7.0.
This solution is for my original question; switch
statements work on the value
of the PropertyInfo
and not its 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/
Upvotes: 7
Reputation: 3221
First of all IsAssignableFrom
is better then just string comparing in case of inherited types.
For example typeof(TextReader).IsAssignableFrom(typeof(StreamReader))
will be true
, because StreamReader
inherited from TextReader
, also work's for interfaces.
If you need only direct comparison, I can suggest create Dictionary<Type,Action<PropertyInfo>>
, for example:
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.
Upvotes: 1
Reputation: 5109
Use the ToString method you have, but instead of literal values use case typeof(string).Name (if that's possible) don't have vs in front of me right now.
Upvotes: 1
Reputation: 171178
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. You are not trying to match constants. You are invoking the IsAssignableFrom
method many times.
Note, that IsAssignableFrom
is not identical to matching types exactly. 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.
Upvotes: 5
Reputation: 21480
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'
}
Upvotes: 3