-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature Request: C# - Runtime parsing of interpolation-tokenized string #2347
Comments
How does that work? Is it expected that the variable or expression embedded within the interpolating string constant will be valid at the point where you interpolate? Where does |
It would work at that place, in that context. In any other place where the interpolated expression is not a valid in-scope resultant, it would throw an error exactly like it does today.
If Only change per my idea is to allow use of a predeclared string variable in the place of a string literal. |
It gets a lot more complicated than that because string interpolation allows you to put quite literally any expression in the string, not just variable names. That's problematic because the compiler can't do anything to ensure that whatever expression is in that string is valid because it has no idea what those identifiers are, and it opens avenues where a string constant could embed malicious or deleterious code into the consuming program. Not to mention, no other language could consume those constants. |
I agree with you. But I still don't understand how that's different from writing the string "there" (versus using a string in a variable). Could you explain that? |
Sure, when you write an interpolated string now the expression within the string has to be validated by the compiler. You can't reference variables that don't exist or embed invalid code. If that code was instead embedded in a const string the compiler can't validate it at that point because those variables don't exist. This would be asking for the compiler to just embed that code as code within the constant and then reinterpret it if you happen to use the constant in an interpolated string. The code could mean (and do) wildly different things at each point you used it. It could even contain malicious code. And if you accidentally forget to interpolate you could expose the code directly. |
Okay. Got it. But the language has so many strange things in it today that would've sounded absurd a couple of years ago. Am happy to wait for this 2-3 releases from now when we might have more going on that pushes this into the realm ofpossible. Put it on some backlog :-) |
@sujayvsarma I believe the issues mentioned by @HaloFour don't make this feature impossible, they make it undesirable. Look at it this way: what you're asking for is effectively to have a "function", but one whose arguments are not specified explicitly, but implicitly based on their names. Such tight coupling between a "function" and the code that calls it is not a good idea. It also means that this feature would not be friendly to IntelliSense: when you're writing the |
We have too many of those in C# already @svick. |
I don't really understand the key benefit of a late-bound interpolation like this. It sounds far more error-prone -- we should endeavor to catch as many errors at compile time as possible. Also, no other expression in C# allows you to use identifiers that don't exist yet, so this isn't exactly idiomatic. |
I'd like someone from the C# team to weigh in on this. |
this is usefull feature, but any unique string (template) will require dynamic compilation, and performance may be terrible, at lest for first run |
@sujayvsarma Actually you are asking for |
If you're looking to provide some sort of templating support, consider using Roslyn's C# Scripting. |
Looks similar yes, but that's NOT what am asking for. My intention is an extension of where interpolated strings are at today. It is a logical next step. |
I don't see how it is. There's no where else in C# where you can define a completely unverifiable expression to have it interpreted at the call-site. That would behave painfully similar to C macros and would probably be quite difficult to troubleshoot when some part of that expression fails to parse at compile-time. It's not as nefarious as, say, an "eval" statement, but it makes it impossible to provide a good tooling or design time support and enables some serious "spooky action at a distance". |
Yes there is. |
Touché, although I don't think that's quite analogous given that |
@HaloFour, I don't think your statement needs modification. Broadly speaking, the behaviour of dynamic is to defer member selection to runtime. The syntax of the expression is still verified by the compiler and you will get an error if it doesn't comply with C# expectations. #iknowyouknowthis |
The language already supports this: string url(string tenantId) => $"https://login.microsoftonline.com/{tenantId}";
//…
string tenId = "contoso.onmicrosoft.com";
//…
Uri u = new Uri(url(tenId)); |
THAT is not the same thing. All you are doing is using a shortcut to define a function and use that. Also, the resulting behaviour is not what I was asking for. |
You could use current language features to rebuilt your string, like so: var tenantId = "placeholder";
FormattableString f = $"https://login.microsoftonline.com/{tenantId}";
var newUri = string.Format(f.Format, "myNewTenantId");
Uri u = new Uri(newUri); But as per your proposal, having the language be able to pull variables that have not been defined yet seems like a confusing recipe for subtle bugs. |
I would really appreciate this feature However, it is a runtime feature. So in anyway the place that this feature would be implemented will be corefx. Not the language feature itself |
Can't you just use a conditional operator in the interpolated string? https://stackoverflow.com/questions/33473752/c-sharp-interpolated-string-with-conditional-operator iMHO the string interpolation shouldn't get access to anything which is not defined in it's template but should be able to support more or less template arguments than given especially with the correct logic in the formatting. You could give your interpolated string a special variable you can control and format as you desire... Perhaps what I would like to see with interpolated string is at runtime a way to enumerate their symbols and expressions but that's not in line with this proposal as it stands... |
I found this very good solution in Stack Overflow. Copying here for easier reading
|
This is what I have did though It use regex to search for static readonly Regex FormatterPattern = new Regex(@"\{([^\{\}]+?)(?:\:([^\{\}]*))?\}",RegexOptions.Multiline);
public static string RegexFormat(this string input,Func<string,object> selector)
{
return FormatterPattern.Replace(input,(match) => {
var capture = match?.Groups?.OfType<Group>().Skip(1).Select((group) => group.Value).ToArray();
if(!(capture?.FirstOrDefault() is string key && selector(key) is var value && value != null))
return match.Value;
return capture.Length > 1 && value is IFormattable formattable ? formattable.ToString(capture[1],null) : value?.ToString();
});
} string text;
int number;
text.RegexFormat("Value : {number:0.0####}",(key) => key == "number" ? 10 : "novalue"); So we could use class or complex data of json or anything Maybe I should also guard that if there is |
This would be useful for resource strings. IMO, what's missing is the ability to convert an interpolated format string like |
Seems like a utility that belongs in a library or the BCL. |
Closing as due to a github bug I can't move this to a discussion, and this issue doesn't have a huge amount of support. Feel free to open a new discussion and reference this issue. |
C# introduced interpolated strings (i.e. $"{varname}") back in 6.0. This is a feature request to extend it in a future iteration of the language/compiler. This could possibly be done using some manner of a compiler trick as well ?
Consider this snippet of code of the as-is scenario:
Snippet 1:
Now, wouldn't it be more useful (reducing lines of code and errors to do with string replacements if this could simply be something like:
Snippet 2:
Note that in the 2nd snippet, I have prefixed the
url
variable in the Uri constructor with a$
indicating that I want the compiler to perform the intended magic.Can this be?
This item was moved from dotnet/roslyn#34145
The text was updated successfully, but these errors were encountered: