Normally I don't recommend using strings directly in queries as this is a SQL injection attack target but in your case you are in complete control over the string being injected so this should be OK
But SQL injection is only one of the issues with this pattern.
One issue is cache littering. That is, if this query runs frequently, with different lists, each command will gets it entry in the SQL Server cache. While this can be mitigated with "optimize for ad hoc workloads", I think it would be wrong as a developer to assume that this setting is in force. And it still creates a cache entry, if a smaller one. But admittedly, if this query runs only once a day, it's not a big issue.
Another possible issue is performance if these lists can be huge. A few hundred are not a problem, but if you send in a list of hundred thousand items, the parse and compile time can be severe.
There are some more alternatives.
One is indeed SqlBulkCopy, but then you need to create a table to copy the values to, and then use that table in the query. This can be a little bulky, if you pardon the pun.
You can also use a table-value parameter. You would need to create a table type for this. I have an article on my web site that shows some examples with table-valued parameters.
Yet other options are to package the parameters into XML or JSON and then shred the values in a temp table in the SQL code.