-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
This proposal was already answered on CodePlex with "too late for C#6", but since C#7 is taking input at the moment, I think it is worth mentioning this again.
Problem:
Current design for FormattableString is:
public class FormattableString {
public string Format { get; }
public object[] Args { get; }
// ...
}Consider two following usages:
// Some future Serilog:
log.Information($"Processed {position} in {elapsedMs:000} ms.");
// Some future Dapper:
connection.Execute($"SELECT * FROM T1 WHERE Id = {id}");In addition to saving the log string, Serilog saves format values as properties on the log entry object. However with current FormattableString the names of these values (position, elapsedMs) would not be available.
Dapper does not really need the names (it can generate parameters named @p1 and @p2), but proper names can improve readability of SQL traces and general SQL debugging.
And another (weird) use case for capturing names of the provided values:
Argument.NotNull($"{x}"); // doesn't actually need the string at all, but uses arg name/valueCompare this with current:
Argument.NotNull(nameof(x), x); // more verbose, not DRYPotential solution
Add IReadOnlyList<string> Names { get; } to the FormattableString.
Those could be generated based on anonymous class property name algorithm:
1. $"{x}, {y}" // Names = "x", "y"
2. $"{x.Y.Z}" // Names = "Z"
3. $"{x}, {5}" // Names = "x", nullOr just literally contain passed in code as a string, e.g. $"{x+5}" // Names = "x+5", though in this case something like Snippets would be a better name.
Since each call site will have a fixed set of names/snippets, each list can be cached per call site once and reused between calls. This means that even the names/snippets aren't used, the performance cost would be minimal.
Pros
- Allows frameworks to be more intelligent when generating a new string from
FormattableStringor recording the parameters somewhere. - Gives some unexpected uses to the
FormattableStringby making it a light-weight way to pass identifier-named value -- e.g. validation. - If code is passed as as string instead of generating a name, this can be used to create an easily cacheable analog of expression trees (by parsing it with Roslyn etc), and various other kinds of 'magic' APIs.
Cons
- If names are generated using anonymous class algorithm, some of them might be null. This might be unexpected -- frameworks can provide fallback, but they have to be careful of those cases.
- If full code is passed as a string, analysis has to be careful so that it is not broken by small variations within the code (e.g. as introduced by refactoring).