public static class MyConsole
{
public static void Test()
{
Console.Out
.Columns(10, 40, 60)
.WriteLine("foo", "bar", "baz")
.WriteLine("LOL", "WUT", "BBQ")
.WriteLine("HA", "ha", "ha");
var cols = Console.Error.Columns(10, 40, 30);
cols.WriteLine("Mary", "Had", "a");
cols.WriteLine("Little", "lamb", "it's");
}
public static ColumnWriter Columns(params int[] widths) => new ColumnWriter(Console.Out, widths);
public static ColumnWriter Columns(this TextWriter writer, params int[] widths) => new ColumnWriter(writer, widths);
public class ColumnWriter
{
public ColumnWriter(TextWriter writer, int[] widths)
{
Debug.Assert(writer != null);
Debug.Assert(widths != null);
_writer = writer;
_widths = widths;
}
private TextWriter _writer;
private int[] _widths;
public ColumnWriter Line()
{
_writer.WriteLine();
return this;
}
public ColumnWriter Write(params object[] args)
{
Debug.Assert(args.Length == _widths.Length);
var count = Math.Min(_widths.Length, args.Length);
for (int idx = 0; idx < count; ++idx)
{
var fmt = "{0," + _widths[idx] + "}";
_writer.Write(fmt, args[idx]);
}
return this;
}
public ColumnWriter WriteLine(params object[] args)
{
return Write(args).Line();
}
}
}
这可以通过为 Columns(string formatString) 和 Columns(this TextWriter writer, string formatString) 添加重载来改善。
坏主意
Columns() 可以用于返回一个委托,用于一些看起来很奇怪的语法(感谢 Evk 向我展示了方法——并且没有比我更喜欢这种语法)。更糟糕的是,我们可以给它多个索引器重载。
无论哪种情况,我都不喜欢新颖的语法。这行得通,但任何在生产代码中使用任何一种的人都会偷羊:
public static class MyConsole
{
public static void Test()
{
// Not a great idea.
MyConsole.WriteLines(10, 10)("foo", "bar")("baz", "planxty");
// Truly awful idea.
MyConsole.Columns(10, 10)["foo", "bar"]["baz", "planxty"].End();
}
public static ColumnWriter Columns(params int[] widths) => new ColumnWriter(widths);
#region Not a great idea
// Evk showed me how to make this work.
public delegate Params Params(params object[] values);
public static Params WriteLines(params int[] widths)
{
var writer = new ColumnWriter(widths);
return new Params(writer.WriteLineParams);
}
#endregion Not a great idea
public class ColumnWriter
{
public ColumnWriter(int[] widths)
{
_widths = widths;
}
private int[] _widths;
#region Truly awful idea.
public ColumnWriter this[object o] => WriteLine(o);
public ColumnWriter this[object o1, object o2] => WriteLine(o1, o2);
public ColumnWriter this[object o1, object o2, object o3] => WriteLine(o1, o2, o3);
// ...moar overloards...
// In C# x[0]; is an expression, not a statement.
// x[0].End(); is a statement. Horrible, most horrible.
// Maybe I should name it FireMe() instead of End()
public void End() { }
#endregion Truly awful idea.
public ColumnWriter Line()
{
Console.WriteLine();
return this;
}
public ColumnWriter Write(params object[] args)
{
var count = Math.Min(_widths.Length, args.Length);
for (int idx = 0; idx < count; ++idx)
{
var fmt = "{0," + _widths[idx] + "}";
Console.Write(fmt, args[idx]);
}
return this;
}
public ColumnWriter WriteLine(params object[] args)
=> Write(args).Line();
#region Not a great idea
public Params WriteLineParams(params object[] args)
{
WriteLine(args);
return WriteLineParams;
}
#endregion Not a great idea
}
}