You-the-user can make C#'s safe, you-the-library-developer can make Java's safe. All you need is for one silly person to assign the C# query to a `var` beforehand and then the behavior's wrong. I'd usually be the first to point out how C# did it earlier and better, but in this case Java's manages to surpass even Rust's, which I didn't think was possible.
> All you need is for one silly person to assign the C# query to a `var` beforehand and then the behavior's wrong.
That would cause a compilation error. `DbSet<TEntity>.FromSql(FormattableString sql)` [0] does not have a string overload. Therefore, if a user assigned the interpolated string to a SQL query to a `var` beforehand, then there would be an implicit conversion to a `string` [1] which will be a type mismatch for the `FromSql` call. The user would have to assign the interpolated string to a `FormattableString` instead of `var` for the program to compile. There is also no implicit conversion for a `string` to a `FormattableString`.
There is a `DbSet<TEntity>.FromSqlRaw(string sql, params object[] parameters)` [2] method that explicitly documents that it is vulnerable to SQL injection.
> You-the-user can make C#'s safe, you-the-library-developer can make Java's safe.
But anyway, Roslyn Analyzers are built into the language. If you throw them away then you might as well call these new template processors off limits too.