1
if(item is classA || item is classB || item is classC || ...)

is there a way to write that line of code more elegantly? I think this can be done but how do you create a collection of types (not instances) so that you can check whether the type of item is inside of that collection?

d1du
  • 296
  • 1
  • 3
  • 12
  • 1
    You can create a `List` and fill it with `TypeOf(ClassA)`, etc... – Rufus L May 28 '21 at 01:15
  • Can you add an interface to each of them? Generally discouraged as just a marker, but it does work. See https://stackoverflow.com/questions/1023068/what-is-the-purpose-of-a-marker-interface – Ian Mercer May 28 '21 at 01:15
  • What should happen inside the if block? – Ramesh May 28 '21 at 01:30

3 Answers3

3

With C# 9 you can do this:

if (item is classA or classB or classC) {}

See https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9#pattern-matching-enhancements for more info.

Ilian
  • 5,113
  • 1
  • 32
  • 41
2

To create a collection of types, use typeof():

new[] { typeof(Class1), typeof(Class2), typeof(Class3) }

This creates a Type[]. However, is can't be used on Type instances. You can use IsAssignableFrom instead. Note that just comparing if the type of item is equal to the array elements is not enough to replicate the behaviour of is - is does more than that. It checks the inheritance hierarchy, and a bunch of other stuff too.

Combine that with Any, you get:

if (new[] { typeof(Class1), typeof(Class2), typeof(Class3) }.Any(x => item.GetType().IsAssignableFrom(x))) {

}

This certainly doesn't look too much more elegant than your original, but if you have a lot of types to check, it will eventually be shorter.

Note that unless all the types have some common members, checking whether an object is any of those types isn't very useful. There isn't anything extra that you suddenly can now do, once you know that item is one of these types. You still can't safely cast it to a specific type.

If all the types do have some common members, consider writing an interface with all the common members, and making those types implement that interface. This way you just need to check if item is that interface!

Sweeper
  • 213,210
  • 22
  • 193
  • 313
0

I'm not sure it is more elegant, but if you want to check whether the item's type is part of a collection you could do

if (new [] { typeof(classA), typeof(classB), typeof(classC) }.Contains(item.GetType()))
{

}

Following the comments, to replicate the is behaviour, you could do

if (new[] { typeof(classA), typeof(classB), typeof(classC) }.Any(x => item.GetType().IsAssignableFrom(x))) 
{

}
Arthur Rey
  • 2,990
  • 3
  • 19
  • 42
  • @Llama The question is "how do you create a collection of types (not instances) so that you can check whether the type of item is inside of that collection?". I can't see how it doesn't answer it? – Arthur Rey May 28 '21 at 01:17
  • 2
    You'd need to use `.IsAssignableFrom` to be equivalent. – Jeremy Lakeman May 28 '21 at 01:17
  • I don't disagree, I just strictly answered his question (he didn't mention inheritance nor his wish to stick to the `is` behaviour) but I get your point and edited my answer. – Arthur Rey May 28 '21 at 01:25