0

Obviously the meaning of "similiar" will be application-dependent.

In my case, I'd like to classify int, Int32, UInt16 and Byte (and other integer types) to be "similar". Same for float, double and Decimal (and other floating point types).

One possible solution might be:

if (    (myObject is int) ||
        (myObject is Byte) ||
        ...)
{
    // Do something with integer types
}
else if (   (myObject is float) ||
            (myObject is double) ||
            ...)
{
    // Do something with floating point types
}

However, this seems overly complex and buggy.

Is there a more efficient way to determine if an Object is "an integer" or "a floating point number" or "a string"?

UPDATE

Some missing information. Using:

  • Visual Studio 2019 Professional v16.8.2
  • Library targets .NET 4.5 (based on other libraries in the solution) which uses C# 5.0
AlainD
  • 5,413
  • 6
  • 45
  • 99
  • 1
    Maybe this would help: https://stackoverflow.com/questions/983030/type-checking-typeof-gettype-or-is –  Apr 14 '21 at 14:22

2 Answers2

2

A switch block (or expression, if it is a simple return):

switch (myObject)
{
    case int:
    case byte:
      // ...
      break;
    case float:
    case double:
      // ...
      break;
}

Note that this is only cleaner to read.

You can also capture the typed value if you like, but this is then per-case, as it won't be "definitely assigned", for example:

switch (myObject)
{
    case int i32:
      // ... can use i32 here
      break;
    case byte u8:
      // ... can use u8 here
      break;
    case float f32:
      // .. can use f32 here
      break;
    case double f64:
      // ... can use f64 here
      break;
}

A "switch expression" is simpler if you are performing a single expression on each:

var x = myObject switch {
    int i32 => someExpressionHere,
    byte u8 => someOtherExpressionHere,
    // etc
    _ => thingToDoForAnythingElse,
};
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Our application currently targets .NET 4.5. The 1st `switch` block does not compile with the error `Feature 'type pattern' is not available in C# 7.3. Please use language version 9.0 or greater.` C#9.0 requires .NET 5.0. Have I understood the error correctly? And is it possible to do something similar in .NET 4.5? – AlainD Apr 14 '21 at 14:30
  • 1
    @AlainD no, C# 9 does **not** require .NET 5 - you just need a newer compiler; assuming you have that (and you probably do, because otherwise *it wouldn't have known what you were trying to do*), you can just do `7.3` in the csproj, and everything should work. **SOME FEATURES** require runtime support - however, the switch changes do not. It will be very obvious when a new .NET version *is* required - it won't compile. – Marc Gravell Apr 14 '21 at 14:38
  • Ok, have specified a different language version by adding `9.0` into the .csproj and this now compiles. Note that `7.3` did not work, with the same compile error as before. I'm using Visual Studio 2019 v16.8.2 (will add that to the question). Have also since discovered that our targeted .NET version (4.5) uses C# 5.0. – AlainD Apr 14 '21 at 14:53
  • You can also do this with an if `if (obj is int num) { Console.WriteLine(num); } ` – Patrick Hollweck Apr 14 '21 at 15:04
  • @MarcGravell C# 9 is compatible only with .NET 5 according to Microsoft. `` is also pretty much deprecated (you can no longer edit it on the VS GUI, and Microsoft recommends removing it from the project file, see "C# language versioning" on MSDN). Of course some of the language features don't need a new CLR and happen to work on the older one, but I wouldn't encourage something that isn't officially supported. – Yarik Apr 14 '21 at 15:11
  • @Yarik that is to simplify the message; almost all features work absolutely perfectly; don't misunderstand me: I do get your point, and from a purist perspective you're right - but: in reality, almost everything *just works* (the places where it gets hairy are things like `init`-accessors, default interface implementation, etc) – Marc Gravell Apr 14 '21 at 15:56
1

If you are still using an older version of Visual Studio and/or don't want to use C# language features that are not officially supported by your current target framework, an alternative may be to switch on the type's TypeCode:

TypeCode typeCode = Type.GetTypeCode(myObject.GetType());
switch (typeCode)
{
    case TypeCode.Int32:
    case TypeCode.Byte:
        //...
        break;
    case TypeCode.Single:
    case TypeCode.Double:
        //...
        break;
}
mm8
  • 163,881
  • 10
  • 57
  • 88