在 Console.WriteLine 中调用 void 方法

Call a void method in Console.WriteLine

我正在开发一个 C# 控制台项目,但我对 C# 还是全新的。我的问题是:我可以在 Console.WriteLine(); 中调用 void 方法吗?也许像

static void ChangeColor()
{
   Console.backgroundColor = ConsoleColor.Red
};

Console.WriteLine("Hello *Calling method *ChangeColor();* * my friend!"); 

我的代码中的示例:

                Console.Write(
$@"
____________________________________________________________________________________________________
|                                                                                                  |
|                         __     __                                                                |
|                        / / \__/\ \                                                               |
|                        \/| /\/\|\/                                                               |");
                DarkBlueTxt();
                Console.Write(
$@"
|                        __||o o||__                                                               |
|                       / . \__/ .  \                                                              |
|                      /.  .(__).  . \                                                             |
|______________________\ .  /__\ .   /_____________________________________________________________|");

您可以检查 ANSI 颜色,但它需要某种控制台模式,这在 link 中有说明。

static void Main(string[] args)
{
    Console.WriteLine("\u001b[31mHello World!\u001b[0m");
}

来源: Using ANSI colour codes in .NET Core Console applications

或许自己做一个辅助方法:

void WriteWithColors(params object[] p){

  foreach(var o in p){
    if(o is ConsoleColor)
      Console.BackgroundColor = (ConsoleColor)o;
    else
      Console.Write(o);
  }
}

然后这样称呼它:

WriteWithColors(ConsoleColor.Red, @"
____________________________________________________________________________________________________
|                                                                                                  |
|                         __     __                                                                |
|                        / / \__/\ \                                                               |
|                        \/| /\/\|\/                                                               |", ConsoleColor.Blue, @"
|                        __||o o||__                                                               |
|                       / . \__/ .  \                                                              |
|                      /.  .(__).  . \                                                             |
|______________________\ .  /__\ .   /_____________________________________________________________|");

编译器会将您的颜色和字符串组合捆绑到一个对象数组中,然后方法中的循环遍历它,根据它是什么(颜色或字符串)更改颜色或打印字符串

如果您不在字符串中使用 {placeholders},那么您不需要在字符串的头部加上 $ btw

只是为了好玩,您可以大量滥用新的 C# 10 Interpolated string handlers 让您编写例如:

WriteColoredText($"First{ConsoleColor.Red}Second");

请不要在实践中实际这样做 -- 这是一个可怕的 hack,没有人会理解。使用 :它可能更清晰,也更简单。但这是对新的内插字符串处理程序的强大功能的有趣探索。

说到这里,开始吧。

首先,我们需要定义我们自己的内插字符串处理程序,我们将包装 StringBuilder.AppendInterpolatedStringHandler,因为这主要是我们想要的。然而,当 ConsoleColor 被写入时,我们将记录下来,以段列表结束,其中每个段是一段文本和写入它的颜色:

[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()));   
    }
}

然后我们需要定义一个接受这个处理程序的方法:

public static void WriteColoredText(ConsoleColorInterpolatedStringHanderhandler)
{
    handler.Finish();
    foreach (var (color, text) in handler.Segments)
    {
        if (color != null)
        {
            Console.BackgroundColor = color.Value;
        }
        Console.Write(text);
    }
}

然后我们可以将内插字符串传递给我们的新 WriteColoredText 方法。任何包含 ConsoleColor 的占位符都会导致背景颜色发生变化。

See it on SharpLab.

要了解发生了什么,请切换到 C# view on SharpLab。重要的一点是编译器已经将我们对 WriteColoredText 的调用写入:

public static void Main()
{
    ConsoleColorInterpolatedStringHander handler = new ConsoleColorInterpolatedStringHander(10, 1);
    handler.AppendLiteral("Hello");
    handler.AppendFormatted(ConsoleColor.Red);
    handler.AppendLiteral("World");
    WriteColoredText(handler);
}

的变体:

void WriteWithColors(params (ConsoleColor? Color, string Text)[] colorizedTextCollection)
{
    foreach (var colorizedText in colorizedTextCollection)
    {
        Console.BackgroundColor = colorizedText.Color ?? Console.BackgroundColor;
        Console.Write(colorizedText.Text);
    }
}
  • 这里您可以传递颜色和文本元组,而不是接收 object 数组
  • 通过这种方法,foreach 的主体变得更简单了

示例用法:

WriteWithColors((ConsoleColor.Red, "red"), 
                (null, "still red"), 
                (ConsoleColor.DarkBlue, "blue"));

谢谢大家!你们都有很好的答案。为了简单起见,我现在将绘图的每个不同颜色的部分放在不同的方法中,然后一个一个地调用部分和颜色方法,这是我认为最简单的方法,即使我不想这样做像那样但不幸的是我想要的似乎不存在。再次感谢您的回答!