Consider the following code:
internal static class Program
{
private static void Main()
{
object value = "Hello";
Console.WriteLine(value.Test(o => o is string));
}
private static bool Test<T>(this T value, Expression<Func<T, bool>> test) =>
test.Compile().Invoke(value);
}
Result:
True
Now, compare to this code:
internal static class Program
{
private static void Main()
{
string? value = "Hello";
Console.WriteLine(value.Test(o => o is null)); // Compiler error
}
private static bool Test<T>(this T value, Expression<Func<T, bool>> test) =>
test.Compile().Invoke(value);
}
Result:
An expression tree cannot contain pattern-matching 'is' expression
I'm curious as to why the latter code produces the above compiler error, but the former code does not, even though it too is also a pattern-matching 'is' expression; i.e. why is type matching allowed, but null matching isn't?
Note: I know that I could use Func<T, bool>
instead of Expression<Func<T, bool>>
but that is beyond the scope of this question.
The usage of is
as a type test (obj is Foo
) is very old, and comes from the earliest days of C#.
The is
keyword was later expanded to include patterns (obj is null
, obj is string s
, etc), first in C# 7, and then further in subsequent versions.
Expressions are stuck at C# 3 for backwards compatibility reasons, so they support type tests but not patterns.