1

I tried to come up with a shorthand solution for an or operator. So I came up with something like this, but the result is always false.

Can someone give some advice on how can I fix this issue? Will this even work at all? If not, are there any other solutions similar to this?

P.S. I know that this question has been asked before, but unfortunately, none of the solutions suited my needs.

The code:

public static bool IsEqualsTo(object o, params object[] p)
{
    for (int i = 0; i < p.Length; i++)
    {
        if (o == p[i])
        { return true; }
    }
    return false;
}

So for example:

From if (MovementState == PMovementState.Walking || MovementState == PMovementState.Idle)

to if (IsEqualsTo(MovementState, PMovementState.Walking, PMovementState.Idle))

or

From if (input.text == "text" || input.text == "text2" || input.text == "text3")

to if (IsEqualsTo(input.text, "text", "text2", "text3"))

Community
  • 1
  • 1
UnknownUser
  • 327
  • 2
  • 14
  • 2
    _I know that this question has been asked before, but unfortunately, none of the solutions suited my needs._ : Can you provide any link to the questions you referring ? – Pac0 Aug 05 '19 at 13:33
  • 1
    And the reason why those answers didn't suit. – DavidG Aug 05 '19 at 13:34
  • 2
    This is really `Enumerable.Contains` but with a `params` array, and it would be easily implemented in terms of that. – Jeroen Mostert Aug 05 '19 at 13:35
  • No repro with the text example. `IsEqualsTo` returns `true` even with `object` – Panagiotis Kanavos Aug 05 '19 at 13:37
  • Also, why does the code you have here not work? It looks fine to me. – DavidG Aug 05 '19 at 13:37
  • @Pac0 Hey there! These are the questions I viewed when I was looking for the possible solution on the topic https://stackoverflow.com/questions/40465720/c-sharp-shorthand-for-2-or-conditions or https://social.msdn.microsoft.com/Forums/en-US/2bba32df-fa2a-4749-8505-5b8eddc4fe9c/shorthand-for-multiple-ors?forum=csharplanguage – UnknownUser Aug 05 '19 at 13:37

2 Answers2

4

You could use a generic version to avoid boxing/unboxing:

public static bool IsEqualsTo<T>(T o, params T[] p)
{
    var comparer = EqualityComparer<T>.Default; // make it an optional parameter
    for (int i = 0; i < p.Length; i++)
    {
        if (comparer.Equals(o, p[i]))
            return true;
    }
    return false;
}

The reason for your issue is that the Object parameter is boxed if a value type like an enum(struct) is passed. This will cause == to return false because it's not the same reference. Use Equals as shown above to fix this issue and use generics to make it more efficient.

As noted you can also shorten the body of the method with LINQ:

return p.Contains(o, comparer);
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • This works great! Thank you :) I guess I should've went with generics from the start, my bad.. – UnknownUser Aug 05 '19 at 13:44
  • 2
    @UnknownUser you can also write `return p.Contains(o)` – Panagiotis Kanavos Aug 05 '19 at 13:46
  • 2
    This code is similar to [Enumerable.Contains](https://github.com/microsoft/referencesource/blob/master/System.Core/System/Linq/Enumerable.cs#L1370) – Panagiotis Kanavos Aug 05 '19 at 13:46
  • 1
    Interesting - .NET Core's [Contains](https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/Contains.cs) explicitly uses the default comparer directly to improve performance! That's worth benchmarking if the results aren't mentioned in any of the .NET Core-related perf articles – Panagiotis Kanavos Aug 05 '19 at 13:52
2

Instead of doing a for loop you can use the Contains method :

public static bool IsEqualsTo(object o, params object[] p)
{
    return p.Contains(o);
}
Guilhem Prev
  • 979
  • 5
  • 17