'Call a void method in Console.WriteLine
I am working on a C# console project, but I am yet totally new in C#. My question is: can I call a void method in Console.WriteLine();? Maybe something like
static void ChangeColor()
{
Console.backgroundColor = ConsoleColor.Red
};
Console.WriteLine("Hello *Calling method *ChangeColor();* * my friend!");
An example from my code:
Console.Write(
$@"
____________________________________________________________________________________________________
| |
| __ __ |
| / / \__/\ \ |
| \/| /\/\|\/ |");
DarkBlueTxt();
Console.Write(
$@"
| __||o o||__ |
| / . \__/ . \ |
| /. .(__). . \ |
|______________________\ . /__\ . /_____________________________________________________________|");
Solution 1:[1]
Just for fun, you can heavily abuse the new C# 10 Interpolated string handlers to let you write e.g.:
WriteColoredText($"First{ConsoleColor.Red}Second");
Please don't actually do this in practice -- it's a horrible hack which noone will understand. Use @CauisJard's answer instead: it's probably clearer, and much simpler. But this is a fun exploration of the power of the new interpolated string handlers.
With that said, here goes.
First, we'll need to define our own interpolated string handler, We'll wrap StringBuilder.AppendInterpolatedStringHandler, as that mainly does what we want. However, when a ConsoleColor is written, we'll record this, ending up with a list of segments, where each segment is a section of text and the color to write it in:
[InterpolatedStringHandler]
public struct ConsoleColorInterpolatedStringHander
{
private readonly StringBuilder sb = new();
private StringBuilder.AppendInterpolatedStringHandler appendHandler;
private ConsoleColor? currentColor = null;
public List<(ConsoleColor?, string)> Segments { get; } = new();
public ConsoleColorInterpolatedStringHander(int literalLength, int formattedCount)
{
appendHandler = new(literalLength, formattedCount, sb);
}
public void AppendLiteral(string value) => appendHandler.AppendLiteral(value);
public void AppendFormatted<T>(T value) => appendHandler.AppendFormatted(value);
public void AppendFormatted<T>(T value, string? format) => appendHandler.AppendFormatted(value, format);
public void AppendFormatted<T>(T value, int alignment) => appendHandler.AppendFormatted(value, alignment);
public void AppendFormatted<T>(T value, int alignment, string? format) => appendHandler.AppendFormatted(value, alignment, format);
public void AppendFormatted(ConsoleColor color)
{
Segments.Add((currentColor, sb.ToString()));
sb.Clear();
currentColor = color;
}
public void Finish()
{
Segments.Add((currentColor, sb.ToString()));
}
}
We then need to define a method which accepts this handler:
public static void WriteColoredText(ConsoleColorInterpolatedStringHanderhandler)
{
handler.Finish();
foreach (var (color, text) in handler.Segments)
{
if (color != null)
{
Console.BackgroundColor = color.Value;
}
Console.Write(text);
}
}
We can then pass an interpolated string to our new WriteColoredText method. Any placeholders which contain a ConsoleColor cause the background color to change.
To get an idea of what's going on, switch to the C# view on SharpLab. The important bit is that the compiler has written our call to WriteColoredText into:
public static void Main()
{
ConsoleColorInterpolatedStringHander handler = new ConsoleColorInterpolatedStringHander(10, 1);
handler.AppendLiteral("Hello");
handler.AppendFormatted(ConsoleColor.Red);
handler.AppendLiteral("World");
WriteColoredText(handler);
}
Solution 2:[2]
You could check ANSI colors, but it requires a certain console mode which is explained in the link.
static void Main(string[] args)
{
Console.WriteLine("\u001b[31mHello World!\u001b[0m");
}
Source: Using ANSI colour codes in .NET Core Console applications
Solution 3:[3]
A variant of Caius Jard's proposed solution:
void WriteWithColors(params (ConsoleColor? Color, string Text)[] colorizedTextCollection)
{
foreach (var colorizedText in colorizedTextCollection)
{
Console.BackgroundColor = colorizedText.Color ?? Console.BackgroundColor;
Console.Write(colorizedText.Text);
}
}
- Instead of receiving an
object array, here you can pass color and text tuples - With this approach the
foreach's body become a bit simpler
Sample usage:
WriteWithColors((ConsoleColor.Red, "red"),
(null, "still red"),
(ConsoleColor.DarkBlue, "blue"));
Solution 4:[4]
Thanks to everybody! You all have really good answers. To keep it simple for now I have placed each different colored part of the drawing in a different method and then called the parts and color methods one by one, that was the easiest way I think, even when I didn't want to do it like that but unfortunately what I wanted seems not to be existing. Thanks again for your answers!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Jeroen van Langen |
| Solution 3 | Peter Csala |
| Solution 4 | Amer |
