I have these extension methods and enum type:
public static bool IsOneOf<T>(this T thing, params T[] things)
{
return things.Contains(thing);
}
public static bool IsOneOf<T>(this T? thing, params T[] things) where T : struct
{
return thing.HasValue && things.Contains(thing.Value);
}
public enum Color { Red, Green, Blue }
The first if
below compiles; the second does not:
if ((x.Y?.Color).IsOneOf(Color.Red, Color.Green))
;
if (x.Y?.Color.IsOneOf(Color.Red, Color.Green))
;
They only vary by the extra set of parentheses. Why do I have to do this?
At first I suspected it was doing a double implicit cast from bool?
to bool
and then back to bool?
, but when I remove the first extension method, it complains there is no implicit cast from bool
to bool?
. I then checked the IL and there were no casts. Decompiling back to C# yields something that looks like:
if (!(y != null ? new Color?(y.Color) : new Color?()).IsOneOf<Color>(new Color[2]
{
Color.Red,
Color.Green
}));
which is fine for the version of the CLR I'm running, and what I expect. What I didn't expect is that x.Y?.Color.IsOneOf(Color.Red, Color.Green)
doesn't compile.
What is going on? Is it simply the way the language was implemented that it requires the ()
?
Update
Here's a screen cap showing the error in context. This is getting even more confusing to me. The error actually makes sense; but what doesn't (in my mind now) is why line 18 wouldn't have the same problem.
IEnumerable<T>
and do it the other way:var colors = new[] { Color.Red, Color.Green }; if (colors.Contains(whatever)) ...
– Profanepublic static bool IsOneOf<T>(this T thing, params T[] things) { return thing != null && things.Contains(thing); }
is legal. – Profane?.
operator is meant to do, it will short-circuit the expression when it encounters a null value? Using()
around it will not allow theIsOneOf
method to be short-circuited, therefore guaranteeing the expression to be evaluated as abool
. – Lecture