IS there a way to pass an array of types to the "is" operator?
I am trying to simplify the syntax of checking an object against multiple types.
Something like:
public static function bool IsOfType(object Obj,params Type[] Types)
This would however require the following usage:
if(X.IsOfType(typeof(int),typeof(float))
{...}
I would like to do something like:
if(X is {int,float})
or
if(X.IsOfType(int,float))
or even
public static bool ISOfType<T[]>(this object Obj){...}
if(X.ISOfType<int,float>())
I think they are all impossible.
If you're okay with passing the types as generic arguments, there is a solution. Unfortunately, C# doesn't support variadic generics. You have to define the function for each generic arity.
public static bool IsOfType<T>(this object obj) => obj is T;
public static bool IsOfType<T1, T2>(this object obj) => obj is T1 || obj is T2;
public static bool IsOfType<T1, T2, T3>(this object obj) => obj is T1 || obj is T2 || obj is T3;
public static bool IsOfType<T1, T2, T3, T4>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4;
public static bool IsOfType<T1, T2, T3, T4, T5>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4 || obj is T5;
public static bool IsOfType<T1, T2, T3, T4, T5, T6>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4 || obj is T5 || obj is T6;
public static bool IsOfType<T1, T2, T3, T4, T5, T6, T7>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4 || obj is T5 || obj is T6 || obj is T7;
public static bool IsOfType<T1, T2, T3, T4, T5, T6, T7, T8>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4 || obj is T5 || obj is T6 || obj is T7 || obj is T8;
I doubt you'll need more than 8 types but if you do, just define more overloads.
With C# 10, you can use pattern matching to test an object for multiple types.
Example:
public bool TestObject<T>(T obj)
{
if (obj is not null and (int or float or uint))
{
// obj is not null and guaranteed to be an int, float or uint
}
}
Example 2 (in case you want to use the value):
public bool TestIntOrFloat<T>(T obj)
{
if (obj is not (int or float))
{
// obj is neither int or float
}
else if (obj is int i)
{
// obj is an integer and can be used with the variable 'i'
}
else if (obj is float f)
{
// obj is a floating number and can be used with the variable 'f'
}
}
It can looks crazy, but you can use the following Fluent syntax:
object someInstance = 5.0;
if(someInstance
.Is<int>()
.Or<double>()) {
// ...
}
Here the fluent-syntax is implemented as follows:
static class FluentIs {
public static IsResult Is<T>(this object target) {
return new IsResult(target, () => target is T);
}
public static IsResult Or<T>(this IsResult prev) {
return new IsResult(prev, (v, x) => v || (x is T));
}
public class IsResult {
Func<bool> value;
object target;
internal IsResult(IsResult r, Func<bool, object, bool> getValue) :
this(r.target, () => getValue(r.value(), r.target)) {
}
internal IsResult(object target, Func<bool> value) {
this.target = target;
this.value = value;
}
// bool Operators
public static bool operator true(IsResult r) { return r.value(); }
public static bool operator false(IsResult r) { return !r.value(); }
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With