Last active
August 23, 2022 12:24
-
-
Save B1Z0N/19b9dfe973b3ec2535f8e5098a96f77e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
using System; | |
public static class Program | |
{ | |
public static Logger logger = new Logger { EnabledLevel = LogLevel.Error }; | |
public static void Main() | |
{ | |
// Overview | |
TestOrdinary(); | |
TestBothStringAndHandlerMethods(); | |
TestConstructor(); | |
TestMultiple(); | |
TestNoArgs(); | |
TestConstString(); | |
TestRefParam(); | |
TestStructConstructorParam(); | |
TestSubstitutedGeneric(); | |
TestDependent(); | |
} | |
public enum LogLevel | |
{ | |
Debug = 0, | |
Info, | |
Warning, | |
Error, | |
Fatal | |
} | |
public partial class Logger | |
{ | |
public LogLevel EnabledLevel; | |
} | |
[InterpolatedStringHandler] | |
public ref partial struct LoggerInterpolatedStringHandler | |
{ | |
private DefaultInterpolatedStringHandler handler; | |
public LoggerInterpolatedStringHandler(int literalLength, int formattedCount, Logger logger, LogLevel level, out bool handlerIsValid) | |
{ | |
handler = default; | |
if (logger.EnabledLevel > level) | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
handler = new(literalLength, formattedCount); | |
} | |
public void AppendLiteral(string s) => handler.AppendLiteral(s); | |
public void AppendFormatted<T>(T t) => handler.AppendFormatted(t); | |
public string ToStringAndClear() => handler.ToStringAndClear(); | |
public override string ToString() => handler.ToStringAndClear(); | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Ordinary custom interpolated string handler | |
////////////////////////////////////////////////////////////////////// | |
public static void TestOrdinary() | |
{ | |
var name = "Fred Silberberg"; | |
logger.Log(LogLevel.Info, $"{name} will never be printed because info is < error!"); | |
} | |
public partial class Logger | |
{ | |
public void Log(LogLevel level, [InterpolatedStringHandlerArgument("", "level")]LoggerInterpolatedStringHandler handler) | |
{ | |
if (EnabledLevel <= level) Console.WriteLine(handler.ToString()); | |
} | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Both string and interpolated string handler methods overloads | |
////////////////////////////////////////////////////////////////////// | |
public static void TestBothStringAndHandlerMethods() | |
{ | |
const string i = "1"; | |
logger.LogBothStringAndHandler(LogLevel.Fatal, $"{i + "1" + $"{i + "1" + $"{i}"}"}" + $"2"); // 111112 | |
logger.LogBothStringAndHandler(LogLevel.Fatal, $"{@"5"}jkl{(i + "2")}1{i + "9"}"); // 5jkl12119 | |
logger.LogBothStringAndHandler(LogLevel.Fatal, $"{"1"}"); // 1 | |
logger.LogBothStringAndHandler(LogLevel.Fatal, $"{1}"); // $"{1}" (non-const since it's int) | |
} | |
public partial class Logger | |
{ | |
public void LogBothStringAndHandler(LogLevel level, [InterpolatedStringHandlerArgument("", "level")]LoggerInterpolatedStringHandler handler) | |
{ | |
if (EnabledLevel <= level) Console.WriteLine(handler.ToString()); | |
} | |
public void LogBothStringAndHandler(LogLevel level, string s) | |
{ | |
if (EnabledLevel <= level) Console.WriteLine(s); | |
} | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Interpolated string handler in constructor | |
////////////////////////////////////////////////////////////////////// | |
public static void TestConstructor() | |
{ | |
var name = "jslkfjdl"; | |
new HandlerTestStruct(logger, LogLevel.Info, $"lo{name}" + $"2"); | |
} | |
public ref struct HandlerTestStruct | |
{ | |
public LoggerInterpolatedStringHandler handler; | |
public HandlerTestStruct(Logger logger, LogLevel level, [InterpolatedStringHandlerArgument("logger", "level")]LoggerInterpolatedStringHandler handler) | |
{ | |
this.handler = handler; | |
} | |
public void Print() | |
{ | |
Console.WriteLine(handler.ToStringAndClear()); | |
} | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Multiple handlers | |
////////////////////////////////////////////////////////////////////// | |
public static void TestMultiple() | |
{ | |
var name = "jslkfjdl"; | |
MultiHandlersTest.Print($"lo{name}" + $"2", $"{name}"); | |
} | |
public ref partial struct LoggerInterpolatedStringHandler | |
{ | |
public LoggerInterpolatedStringHandler(int literalLength, int formattedCount, out bool handlerIsValid) | |
{ | |
handler = new(literalLength, formattedCount); | |
handlerIsValid = true; | |
} | |
} | |
public static class MultiHandlersTest | |
{ | |
public static void Print( | |
[InterpolatedStringHandlerArgument()] LoggerInterpolatedStringHandler handler1, | |
[InterpolatedStringHandlerArgument()] LoggerInterpolatedStringHandler handler2) | |
{ | |
Console.WriteLine(handler1.ToStringAndClear()); | |
Console.WriteLine(handler2.ToStringAndClear()); | |
} | |
} | |
////////////////////////////////////////////////////////////////////// | |
// No args | |
////////////////////////////////////////////////////////////////////// | |
public static void TestNoArgs() | |
{ | |
var time = DateTime.Now; | |
logger.LogNoArgs(LogLevel.Error, $"Error Level. CurrentTime: {time}. This is an error. It will be printed." + $"1"); | |
} | |
public partial class Logger | |
{ | |
public void LogNoArgs(LogLevel level, string msg) | |
{ | |
if (EnabledLevel < level) return; | |
Console.WriteLine(msg); | |
} | |
public void LogNoArgs(LogLevel level, LoggerInterpolatedStringHandler builder) | |
{ | |
if (EnabledLevel < level) return; | |
Console.WriteLine(builder.ToStringAndClear()); | |
} | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Only handler method for const interpolated string | |
////////////////////////////////////////////////////////////////////// | |
public static void TestConstString() | |
{ | |
const string i = "1"; | |
logger.Log(LogLevel.Error, $"{i + "1" + $"{i + "1" + $"{i}"}"}" + $"2"); // 111112 | |
logger.Log(LogLevel.Error, $"{@"5"}jkl{(i + "2")}1{i + "9"}"); // 5jkl12119 | |
logger.Log(LogLevel.Error, $"{"1"}"); // 1 | |
logger.Log(LogLevel.Error, $"{1}"); // $"{1}" (non-const since it's int) | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Ref param interpolated string handler | |
////////////////////////////////////////////////////////////////////// | |
public static void TestRefParam() | |
{ | |
var time = DateTime.Now; | |
logger.LogRefParam(LogLevel.Error, $"Error Level. CurrentTime: {time}. This is an error. It will be printed." + $"1"); | |
} | |
public partial class Logger | |
{ | |
public void LogRefParam(LogLevel level, string msg) | |
{ | |
if (EnabledLevel < level) return; | |
Console.WriteLine(msg); | |
} | |
public void LogRefParam(LogLevel level, ref LoggerInterpolatedStringHandler builder) | |
{ | |
if (EnabledLevel < level) return; | |
Console.WriteLine(builder.ToStringAndClear()); | |
} | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Struct constructor param interpolated string handler | |
////////////////////////////////////////////////////////////////////// | |
public static void TestStructConstructorParam() | |
{ | |
var s = new Struct(); | |
s.Print($"Struct handler {"text"}"); | |
} | |
public struct Struct | |
{ | |
public string Name = "Mykyta"; | |
public Struct() {} | |
public void Print([InterpolatedStringHandlerArgument("")] LoggerInterpolatedStringHandler handler) | |
{ | |
Console.WriteLine(handler.ToStringAndClear()); | |
} | |
} | |
public ref partial struct LoggerInterpolatedStringHandler | |
{ | |
public LoggerInterpolatedStringHandler(int literalLength, int formattedCount, Struct s, out bool handlerIsValid) | |
{ | |
handler = default; | |
if (s.Name != "Mykyta") | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
handler = new(literalLength, formattedCount); | |
} | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Substituted generic interpolated string handler | |
////////////////////////////////////////////////////////////////////// | |
public static void TestSubstitutedGeneric() | |
{ | |
var name = "jslkfjdl"; | |
var gen = new Generic<int>() { field = 5 }; | |
gen.Print($"lo{name}" + $"2"); | |
} | |
public class Generic<T> | |
{ | |
public T field; | |
public void Print( | |
[InterpolatedStringHandlerArgument("")] SubstitutedGenericInterpolatedStringHandler<T> handler) | |
{ | |
Console.WriteLine(handler.ToStringAndClear()); | |
} | |
} | |
[InterpolatedStringHandler] | |
public ref struct SubstitutedGenericInterpolatedStringHandler<T> | |
{ | |
private DefaultInterpolatedStringHandler handler; | |
public SubstitutedGenericInterpolatedStringHandler(int literalLength, int formattedCount, Generic<T> gen, out bool handlerIsValid) | |
{ | |
handler = default; | |
if (gen.field.Equals(default(T))) | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
handler = new(literalLength, formattedCount); | |
} | |
public void AppendLiteral(string s) => handler.AppendLiteral(s); | |
public void AppendFormatted<T>(T t) => handler.AppendFormatted(t); | |
public string ToStringAndClear() => handler.ToStringAndClear(); | |
public override string ToString() => handler.ToStringAndClear(); | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Test dependent interpolated string handlers | |
////////////////////////////////////////////////////////////////////// | |
public static void TestDependent() | |
{ | |
var dh = new DependentHandlers(); | |
dh.Print($"firstHandlerText", $"secondHandlerText"); | |
} | |
public class DependentHandlers | |
{ | |
public string Name = "Mykyta"; | |
public void Print( | |
[InterpolatedStringHandlerArgument("")] DependableInterpolatedStringHandler handler, | |
[InterpolatedStringHandlerArgument("", "handler")] DependentInterpolatedStringHandler dependentHandler) | |
{ | |
Console.WriteLine(dependentHandler.ToStringAndClear()); | |
} | |
} | |
// The handler that will actually "build" the interpolated string" | |
[InterpolatedStringHandler] | |
public ref struct DependentInterpolatedStringHandler | |
{ | |
private DependableInterpolatedStringHandler handler; | |
public DependentInterpolatedStringHandler(int literalLength, int formattedCount, DependentHandlers dh, DependableInterpolatedStringHandler handler, out bool handlerIsValid) | |
{ | |
this.handler = handler; | |
if (dh.Name != "Mykyta") | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
} | |
public void AppendLiteral(string s) => handler.AppendLiteral(s); | |
public void AppendFormatted<T>(T t) => handler.AppendFormatted(t); | |
public string ToStringAndClear() => handler.ToStringAndClear(); | |
public override string ToString() => handler.ToStringAndClear(); | |
} | |
[InterpolatedStringHandler] | |
public ref struct DependableInterpolatedStringHandler | |
{ | |
private DefaultInterpolatedStringHandler handler; | |
public DependableInterpolatedStringHandler(int literalLength, int formattedCount, DependentHandlers dh, out bool handlerIsValid) | |
{ | |
handler = default; | |
if (dh.Name != "Mykyta") | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
handler = new(literalLength, formattedCount); | |
} | |
public void AppendLiteral(string s) => handler.AppendLiteral(s); | |
public void AppendFormatted<T>(T t) => handler.AppendFormatted(t); | |
public string ToStringAndClear() => handler.ToStringAndClear(); | |
public override string ToString() => handler.ToStringAndClear(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
using System; | |
public static class Program | |
{ | |
public static void Main() | |
{ | |
const string i = "1"; | |
var logger = new Logger() { EnabledLevel = LogLevel.Warning }; | |
logger.Log(LogLevel.Error, $"{i + "1" + $"{i + "1" + $"{i}"}"}" + $"2"); // 111112 | |
logger.Log(LogLevel.Error, $"{@"5"}jkl{(i + "2")}1{i + "9"}"); // 5jkl12119 | |
logger.Log(LogLevel.Error, $"{"1"}"); // 1 | |
logger.Log(LogLevel.Error, $"{1}"); // $"{1}" (non-const since it's int) | |
} | |
static Logger GetLogger(LogLevel level) | |
{ | |
return new Logger { EnabledLevel = level }; | |
} | |
public enum LogLevel | |
{ | |
Debug = 0, | |
Info, | |
Warning, | |
Error, | |
Fatal | |
} | |
public class Logger | |
{ | |
// Initialization code omitted | |
public LogLevel EnabledLevel; | |
public void Log(LogLevel level, [InterpolatedStringHandlerArgument("", "level")]LoggerInterpolatedStringHandler handler) | |
{ | |
if (EnabledLevel <= level) Console.WriteLine(handler.ToString()); | |
} | |
public void Log(LogLevel level, string s) | |
{ | |
if (EnabledLevel <= level) Console.WriteLine(s); | |
} | |
} | |
// The handler that will actually "build" the interpolated string" | |
[InterpolatedStringHandler] | |
public ref struct LoggerInterpolatedStringHandler | |
{ | |
private DefaultInterpolatedStringHandler handler; | |
public LoggerInterpolatedStringHandler(int literalLength, int formattedCount, Logger logger, LogLevel level, out bool handlerIsValid) | |
{ | |
handler = default; | |
if (logger.EnabledLevel > level) | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
handler = new(literalLength, formattedCount); | |
} | |
public void AppendLiteral(string s) | |
{ | |
handler.AppendLiteral(s); | |
} | |
public void AppendFormatted<T>(T t) | |
{ | |
handler.AppendFormatted(t); | |
} | |
public string ToStringAndClear() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
public override string ToString() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
} | |
// see more here: https://sergeyteplyakov.github.io/Blog/c%2310/2021/11/08/Dissecing-Interpolated-Strings-Improvements-In-CSharp-10.html | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
using System; | |
public static class Program | |
{ | |
public static void Main() | |
{ | |
var name = "jslkfjdl"; | |
var a = new A($"lo{name}" + $"2"); | |
} | |
public ref struct A | |
{ | |
public string Name = "Mykyta"; | |
public ConstructorInterpolatedStringHandler handler; | |
public A([InterpolatedStringHandlerArgument("")] ConstructorInterpolatedStringHandler handler) | |
{ | |
this.handler = handler; | |
} | |
public void Print() | |
{ | |
Console.WriteLine(handler.ToStringAndClear()); | |
} | |
} | |
// The handler that will actually "build" the interpolated string" | |
[InterpolatedStringHandler] | |
public ref struct ConstructorInterpolatedStringHandler | |
{ | |
private DefaultInterpolatedStringHandler handler; | |
public ConstructorInterpolatedStringHandler(int literalLength, int formattedCount, A clas, out bool handlerIsValid) | |
{ | |
if (clas.Name == "Mykyta") | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
handler = new(literalLength, formattedCount); | |
} | |
public void AppendLiteral(string s) | |
{ | |
handler.AppendLiteral(s); | |
} | |
public void AppendFormatted<T>(T t) | |
{ | |
handler.AppendFormatted(t); | |
} | |
public string ToStringAndClear() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
public override string ToString() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
} | |
// see more here: https://sergeyteplyakov.github.io/Blog/c%2310/2021/11/08/Dissecing-Interpolated-Strings-Improvements-In-CSharp-10.html | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
using System; | |
public static class Program | |
{ | |
public static void Main() | |
{ | |
var mh = new MultiHandlers(); | |
mh.Print($"firstHandlerText", $"secondHandlerText"); | |
} | |
public class MultiHandlers | |
{ | |
public string Name = "Mykyta"; | |
public void Print( | |
[InterpolatedStringHandlerArgument("")] InterpolatedStringHandler handler, | |
[InterpolatedStringHandlerArgument("", "handler")] DependentInterpolatedStringHandler dependentHandler) | |
{ | |
Console.WriteLine(dependentHandler.ToStringAndClear()); | |
} | |
} | |
// The handler that will actually "build" the interpolated string" | |
[InterpolatedStringHandler] | |
public ref struct DependentInterpolatedStringHandler | |
{ | |
private InterpolatedStringHandler handler; | |
public DependentInterpolatedStringHandler(int literalLength, int formattedCount, MultiHandlers mh, InterpolatedStringHandler handler, out bool handlerIsValid) | |
{ | |
this.handler = handler; | |
if (mh.Name != "Mykyta") | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
} | |
public void AppendLiteral(string s) | |
{ | |
handler.AppendLiteral(s); | |
} | |
public void AppendFormatted<T>(T t) | |
{ | |
handler.AppendFormatted(t); | |
} | |
public string ToStringAndClear() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
public override string ToString() | |
{ | |
return this.ToStringAndClear(); | |
} | |
} | |
[InterpolatedStringHandler] | |
public ref struct InterpolatedStringHandler | |
{ | |
private DefaultInterpolatedStringHandler handler; | |
public InterpolatedStringHandler(int literalLength, int formattedCount, MultiHandlers mh, out bool handlerIsValid) | |
{ | |
handler = default; | |
if (mh.Name != "Mykyta") | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
handler = new(literalLength, formattedCount); | |
} | |
public void AppendLiteral(string s) | |
{ | |
handler.AppendLiteral(s); | |
} | |
public void AppendFormatted<T>(T t) | |
{ | |
handler.AppendFormatted(t); | |
} | |
public string ToStringAndClear() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
public override string ToString() | |
{ | |
return this.ToStringAndClear(); | |
} | |
} | |
// see more here: https://sergeyteplyakov.github.io/Blog/c%2310/2021/11/08/Dissecing-Interpolated-Strings-Improvements-In-CSharp-10.html | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
using System; | |
public static class Program | |
{ | |
public static void Main() | |
{ | |
Logger logger = GetLogger(LogLevel.Error); | |
var name = "Fred Silberberg"; | |
logger.Log(LogLevel.Info, $"{name} will never be printed because info is < error!"); | |
} | |
public static Logger GetLogger(LogLevel level) | |
{ | |
return new Logger { EnabledLevel = level }; | |
} | |
public enum LogLevel | |
{ | |
Debug = 0, | |
Info, | |
Warning, | |
Error, | |
Fatal | |
} | |
public class Logger | |
{ | |
// Initialization code omitted | |
public LogLevel EnabledLevel; | |
public void Log(LogLevel level, [InterpolatedStringHandlerArgument("", "level")]LoggerInterpolatedStringHandler handler) | |
{ | |
if (EnabledLevel <= level) Console.WriteLine(handler.ToString()); | |
} | |
} | |
// The handler that will actually "build" the interpolated string" | |
[InterpolatedStringHandler] | |
public ref struct LoggerInterpolatedStringHandler | |
{ | |
private DefaultInterpolatedStringHandler handler; | |
public LoggerInterpolatedStringHandler(int literalLength, int formattedCount, Logger logger, LogLevel level, out bool handlerIsValid) | |
{ | |
handler = default; | |
if (logger.EnabledLevel > level) | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
handler = new(literalLength, formattedCount); | |
} | |
public void AppendLiteral(string s) | |
{ | |
handler.AppendLiteral(s); | |
} | |
public void AppendFormatted<T>(T t) | |
{ | |
handler.AppendFormatted(t); | |
} | |
public string ToStringAndClear() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
public override string ToString() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
} | |
// see more here: https://sergeyteplyakov.github.io/Blog/c%2310/2021/11/08/Dissecing-Interpolated-Strings-Improvements-In-CSharp-10.html | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
using System; | |
public static class Program | |
{ | |
public static void Main() | |
{ | |
var name = "jslkfjdl"; | |
var mh = new MultiHandlers(); | |
mh.Print($"lo{name}" + $"2", $"{name}"); | |
} | |
public class MultiHandlers | |
{ | |
public string Name = "Mykyta"; | |
public void Print( | |
[InterpolatedStringHandlerArgument("")] MultiInterpolatedStringHandler handler1, | |
[InterpolatedStringHandlerArgument("")] MultiInterpolatedStringHandler handler2) | |
{ | |
Console.WriteLine(handler1.ToStringAndClear()); | |
Console.WriteLine(handler2.ToStringAndClear()); | |
} | |
} | |
// The handler that will actually "build" the interpolated string" | |
[InterpolatedStringHandler] | |
public ref struct MultiInterpolatedStringHandler | |
{ | |
private DefaultInterpolatedStringHandler handler; | |
public MultiInterpolatedStringHandler(int literalLength, int formattedCount, MultiHandlers mh, out bool handlerIsValid) | |
{ | |
handler = default; | |
if (mh.Name != "Mykyta") | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
handler = new(literalLength, formattedCount); | |
} | |
public void AppendLiteral(string s) | |
{ | |
handler.AppendLiteral(s); | |
} | |
public void AppendFormatted<T>(T t) | |
{ | |
handler.AppendFormatted(t); | |
} | |
public string ToStringAndClear() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
public override string ToString() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
} | |
// see more here: https://sergeyteplyakov.github.io/Blog/c%2310/2021/11/08/Dissecing-Interpolated-Strings-Improvements-In-CSharp-10.html | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
using System.Text; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Threading.Tasks; | |
public static class Program | |
{ | |
public static void Main() | |
{ | |
var logger = new Logger() { EnabledLevel = LogLevel.Warning }; | |
var time = DateTime.Now; | |
logger.LogMessage(LogLevel.Error, $"Error Level. CurrentTime: {time}. This is an error. It will be printed." + $"1"); | |
} | |
public enum LogLevel | |
{ | |
Off, | |
Critical, | |
Error, | |
Warning, | |
Information, | |
Trace | |
} | |
public class Logger | |
{ | |
public LogLevel EnabledLevel { get; init; } = LogLevel.Error; | |
public void LogMessage(LogLevel level, string msg) | |
{ | |
if (EnabledLevel < level) return; | |
Console.WriteLine(msg); | |
} | |
public void LogMessage(LogLevel level, NoArgsAttrInterpolatedStringHandler builder) | |
{ | |
if (EnabledLevel < level) return; | |
Console.WriteLine(builder.GetFormattedText()); | |
} | |
} | |
///////////////////////////////////////////////// | |
//// Interpolated String Handler pattern | |
///////////////////////////////////////////////// | |
[InterpolatedStringHandler] | |
public ref struct NoArgsAttrInterpolatedStringHandler | |
{ | |
// Storage for the built-up string | |
StringBuilder builder; | |
public NoArgsAttrInterpolatedStringHandler(int literalLength, int formattedCount) | |
{ | |
builder = new StringBuilder(literalLength); | |
Console.WriteLine($"\tliteral length: {literalLength}, formattedCount: {formattedCount}"); | |
} | |
public void AppendLiteral(string s) | |
{ | |
Console.WriteLine($"\tAppendLiteral called: {{{s}}}"); | |
builder.Append(s); | |
Console.WriteLine($"\tAppended the literal string"); | |
} | |
public void AppendFormatted<T>(T t) | |
{ | |
Console.WriteLine($"\tAppendFormatted called: {{{t}}} is of type {typeof(T)}"); | |
builder.Append(t?.ToString()); | |
Console.WriteLine($"\tAppended the formatted object"); | |
} | |
internal string GetFormattedText() => builder.ToString(); | |
} | |
// see more here: https://sergeyteplyakov.github.io/Blog/c%2310/2021/11/08/Dissecing-Interpolated-Strings-Improvements-In-CSharp-10.html | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
using System; | |
public static class Program | |
{ | |
public static void Main() | |
{ | |
const string i = "1"; | |
var logger = new Logger() { EnabledLevel = LogLevel.Warning }; | |
logger.Log(LogLevel.Error, $"{i + "1" + $"{i + "1" + $"{i}"}"}" + $"2"); // 111112 | |
logger.Log(LogLevel.Error, $"{@"5"}jkl{(i + "2")}1{i + "9"}"); // 5jkl12119 | |
logger.Log(LogLevel.Error, $"{"1"}"); // 1 | |
logger.Log(LogLevel.Error, $"{1}"); // $"{1}" (non-const since it's int) | |
} | |
static Logger GetLogger(LogLevel level) | |
{ | |
return new Logger { EnabledLevel = level }; | |
} | |
public enum LogLevel | |
{ | |
Debug = 0, | |
Info, | |
Warning, | |
Error, | |
Fatal | |
} | |
public class Logger | |
{ | |
// Initialization code omitted | |
public LogLevel EnabledLevel; | |
public void Log(LogLevel level, [InterpolatedStringHandlerArgument("", "level")]LoggerInterpolatedStringHandler handler) | |
{ | |
if (EnabledLevel <= level) Console.WriteLine(handler.ToString()); | |
} | |
} | |
///////////////////////////////////////////////// | |
//// Interpolated String Handler pattern | |
///////////////////////////////////////////////// | |
// The handler that will actually "build" the interpolated string" | |
[InterpolatedStringHandler] | |
public ref struct LoggerInterpolatedStringHandler | |
{ | |
private DefaultInterpolatedStringHandler handler; | |
public LoggerInterpolatedStringHandler(int literalLength, int formattedCount, Logger logger, LogLevel level, out bool handlerIsValid) | |
{ | |
handler = default; | |
if (logger.EnabledLevel > level) | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
handler = new(literalLength, formattedCount); | |
} | |
public void AppendLiteral(string s) | |
{ | |
handler.AppendLiteral(s); | |
} | |
public void AppendFormatted<T>(T t) | |
{ | |
handler.AppendFormatted(t); | |
} | |
public string ToStringAndClear() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
public override string ToString() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
} | |
// see more here: https://sergeyteplyakov.github.io/Blog/c%2310/2021/11/08/Dissecing-Interpolated-Strings-Improvements-In-CSharp-10.html | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
using System.Text; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Threading.Tasks; | |
public static class Program | |
{ | |
public static void Main() | |
{ | |
var logger = new Logger() { EnabledLevel = LogLevel.Warning }; | |
var time = DateTime.Now; | |
logger.LogMessage(LogLevel.Error, $"Error Level. CurrentTime: {time}. This is an error. It will be printed." + $"1"); | |
} | |
public enum LogLevel | |
{ | |
Off, | |
Critical, | |
Error, | |
Warning, | |
Information, | |
Trace | |
} | |
public class Logger | |
{ | |
public LogLevel EnabledLevel { get; init; } = LogLevel.Error; | |
public void LogMessage(LogLevel level, string msg) | |
{ | |
if (EnabledLevel < level) return; | |
Console.WriteLine(msg); | |
} | |
public void LogMessage(LogLevel level, ref RefParamInterpolatedStringHandler builder) | |
{ | |
if (EnabledLevel < level) return; | |
Console.WriteLine(builder.GetFormattedText()); | |
} | |
} | |
///////////////////////////////////////////////// | |
//// Interpolated String Handler pattern | |
///////////////////////////////////////////////// | |
[InterpolatedStringHandler] | |
public ref struct RefParamInterpolatedStringHandler | |
{ | |
// Storage for the built-up string | |
StringBuilder builder; | |
public RefParamInterpolatedStringHandler(int literalLength, int formattedCount) | |
{ | |
builder = new StringBuilder(literalLength); | |
Console.WriteLine($"\tliteral length: {literalLength}, formattedCount: {formattedCount}"); | |
} | |
public void AppendLiteral(string s) | |
{ | |
Console.WriteLine($"\tAppendLiteral called: {{{s}}}"); | |
builder.Append(s); | |
Console.WriteLine($"\tAppended the literal string"); | |
} | |
public void AppendFormatted<T>(T t) | |
{ | |
Console.WriteLine($"\tAppendFormatted called: {{{t}}} is of type {typeof(T)}"); | |
builder.Append(t?.ToString()); | |
Console.WriteLine($"\tAppended the formatted object"); | |
} | |
internal string GetFormattedText() => builder.ToString(); | |
} | |
// see more here: https://sergeyteplyakov.github.io/Blog/c%2310/2021/11/08/Dissecing-Interpolated-Strings-Improvements-In-CSharp-10.html | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
using System; | |
///////////////////////////////////////////////// | |
//// Usage | |
///////////////////////////////////////////////// | |
var s = new Struct(); | |
s.Print($"Struct handler {"text"}"); | |
/////////////////////////////////////////////////using System.Runtime.CompilerServices; | |
using System; | |
public static class Program | |
{ | |
public static void Main() | |
{ | |
var s = new Struct(); | |
s.Print($"Struct handler {"text"}"); | |
} | |
public struct Struct | |
{ | |
public string Name = "Mykyta"; | |
public Struct() {} | |
public void Print([InterpolatedStringHandlerArgument("")] StructInterpolatedStringHandler handler) | |
{ | |
Console.WriteLine(handler.ToStringAndClear()); | |
} | |
} | |
///////////////////////////////////////////////// | |
//// Interpolated String Handler pattern | |
///////////////////////////////////////////////// | |
[InterpolatedStringHandler] | |
public ref struct StructInterpolatedStringHandler | |
{ | |
private DefaultInterpolatedStringHandler handler; | |
public StructInterpolatedStringHandler(int literalLength, int formattedCount, Struct s, out bool handlerIsValid) | |
{ | |
handler = default; | |
if (s.Name != "Mykyta") | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
handler = new(literalLength, formattedCount); | |
} | |
public void AppendLiteral(string s) | |
{ | |
handler.AppendLiteral(s); | |
} | |
public void AppendFormatted<T>(T t) | |
{ | |
handler.AppendFormatted(t); | |
} | |
public string ToStringAndClear() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
public override string ToString() | |
{ | |
return this.ToStringAndClear(); | |
} | |
} | |
// see more here: https://sergeyteplyakov.github.io/Blog/c%2310/2021/11/08/Dissecing-Interpolated-Strings-Improvements-In-CSharp-10.html | |
} | |
//// Struct | |
///////////////////////////////////////////////// | |
public struct Struct | |
{ | |
public string Name = "Mykyta"; | |
public Struct() {} | |
public void Print([InterpolatedStringHandlerArgument("")] StructInterpolatedStringHandler handler) | |
{ | |
Console.WriteLine(handler.ToStringAndClear()); | |
} | |
} | |
///////////////////////////////////////////////// | |
//// Interpolated String Handler pattern | |
///////////////////////////////////////////////// | |
[InterpolatedStringHandler] | |
public ref struct StructInterpolatedStringHandler | |
{ | |
private DefaultInterpolatedStringHandler handler; | |
public StructInterpolatedStringHandler(int literalLength, int formattedCount, Struct s, out bool handlerIsValid) | |
{ | |
handler = default; | |
if (s.Name != "Mykyta") | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
handler = new(literalLength, formattedCount); | |
} | |
public void AppendLiteral(string s) | |
{ | |
handler.AppendLiteral(s); | |
} | |
public void AppendFormatted<T>(T t) | |
{ | |
handler.AppendFormatted(t); | |
} | |
public string ToStringAndClear() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
public override string ToString() | |
{ | |
return this.ToStringAndClear(); | |
} | |
} | |
// see more here: https://sergeyteplyakov.github.io/Blog/c%2310/2021/11/08/Dissecing-Interpolated-Strings-Improvements-In-CSharp-10.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.CompilerServices; | |
using System; | |
public static class Program | |
{ | |
public static void Main() | |
{ | |
var name = "jslkfjdl"; | |
var gen = new Generic<int>() { field = 5 }; | |
gen.Print($"lo{name}" + $"2"); | |
} | |
public class Generic<T> | |
{ | |
public T field; | |
public void Print( | |
[InterpolatedStringHandlerArgument("")] SubstitutedGenericInterpolatedStringHandler<T> handler) | |
{ | |
Console.WriteLine(handler.ToStringAndClear()); | |
} | |
} | |
// The handler that will actually "build" the interpolated string" | |
[InterpolatedStringHandler] | |
public ref struct SubstitutedGenericInterpolatedStringHandler<T> | |
{ | |
private DefaultInterpolatedStringHandler handler; | |
public SubstitutedGenericInterpolatedStringHandler(int literalLength, int formattedCount, Generic<T> gen, out bool handlerIsValid) | |
{ | |
handler = default; | |
if (gen.field.Equals(default(T))) | |
{ | |
handlerIsValid = false; | |
return; | |
} | |
handlerIsValid = true; | |
handler = new(literalLength, formattedCount); | |
} | |
public void AppendLiteral(string s) | |
{ | |
handler.AppendLiteral(s); | |
} | |
public void AppendFormatted<T1>(T1 t) | |
{ | |
handler.AppendFormatted(t); | |
} | |
public string ToStringAndClear() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
public override string ToString() | |
{ | |
return handler.ToStringAndClear(); | |
} | |
} | |
// see more here: https://sergeyteplyakov.github.io/Blog/c%2310/2021/11/08/Dissecing-Interpolated-Strings-Improvements-In-CSharp-10.html | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment