There's nothing in the language to support an argument having to be a string literal, no. I think that would be an odd language "feature", personally.
What I would advise instead is to create a MessageTemplate
class or something like that, and change your method to accept a MessageTemplate
parameter.
The MessageTemplate
class can then have a specific set of instances, which would contain all the strings you need. For example:
public sealed class MessageTemplate
{
public static MessageTemplate InvalidFilter { get; } =
new MessageTemplate("invalid_filter");
public static MessageTemplate Success { get; } =
new MessageTemplate("success");
public string Name { get; }
private MessageTemplate(string name) => Name = name;
}
Then the method calls would be like this:
Message.Create(MessageTemplate.Success);
Advantages:
- The valid strings are all in a single place, rather than scattered through the codebase
- The calling code can use a useful name (e.g. "Success") even if the underlying string name is less useful (e.g. "x"), which makes it easier to read
- You can pass
MessageTemplate
references around safely, knowing that they are message templates rather than just arbitrary strings
If you really wanted to only accept string literals, your best bet would probably be to create an attribute for this purpose, and then write a Roslyn analyzer. That would check every method invocation, and validate that if the parameter had the attribute, the argument was a string literal.
Personally I think that has the undesirable effect of scattering these magic, brittle string constants all over the codebase, but it's the closest you'll get to the exact behavior you've requested. It will only have an effect when building with Roslyn, of course.