String.Format扩展方法
本文关键字:方法 扩展 Format String | 更新日期: 2023-09-27 18:22:15
我有:
public static string Format(this string text, params object[] args)
{
return string.Format(text, args);
}
所以我可以做:
"blablabla {0}".Format(variable1);
它是好的/坏的吗?它能变得更短吗?我想让字符串无缝构建,就像写文本一样,不用担心参数和东西的前后:
// bad
return "date: " + DateTime.Now.ToString("dd.MM.yyyy") + "'ntime: " + DateTime.Now.ToString("mm:HH:ss") + "'nuser: " + _user + " (" + _status + ")";
// better, but you have to deal with order of {0}...{n} and order of parameters
return string.Format("date: {0}'ntime: {1}'user: {2} ({3})", ...);
// ideal
return "date: {DateTime.Now{dd:MM:yyyy}}'ntime: {...}'nuser: {_user} ({_status})";
好吧,有一件糟糕的事情是,通过只有一个params object[]
方法,您可以强制每个调用分配额外的数组。
您可能会注意到,string.Format
有一系列重载,用于获取较低数量的参数(这些参数非常常用)——我建议复制它们。
您的"理想"场景可以通过重写string.Format
方法来完成,但您需要传入值,即
return "date: {date}'ntime: {...}'nuser: {_user} ({_status})"
.Format(new { date = DateTime.Now, _user, _status });
(并使用您自己的自定义Format
方法,或类似的方法)-但请注意,这会强制每次调用都有一个新的对象实例。
实际上,mono编译器曾经有一个实验性的标志来直接启用它。我不知道它是否得到维护。
这与你的理想不太匹配,但类似的东西可能对你有用:
public static class Extensions
{
public static string Format(this object data, string format)
{
var values = new List<object>();
var type = data.GetType();
format = Regex.Replace(format, @"(^|[^{])'{([^{}]+)'}([^}]|$)", x =>
{
var keyValues = Regex.Split(x.Groups[2].Value,
"^([^:]+):?(.*)$")
.Where(y => !string.IsNullOrEmpty(y));
var key = keyValues.ElementAt(0);
var valueFormat = keyValues.Count() > 1 ?
":" + keyValues.ElementAt(1) :
string.Empty;
var value = GetValue(key, data, type);
values.Add(value);
return string.Format("{0}{{{1}{2}}}{3}",
x.Groups[1].Value,
values.Count - 1,
valueFormat,
x.Groups[3].Value);
});
return string.Format(format, values.ToArray());
}
private static object GetValue(string name, object data, Type type)
{
var info = type.GetProperty(name);
return info.GetValue(data, new object[0]);
}
}
这应该允许你对任何对象进行这种格式化:
new {Person = "Me", Location = "On holiday"}
.Format("{Person} is currently {Location}");
它还允许您添加一些格式:
new {Person = "Me", Until = new DateTime(2013,8,1)}
.Format("{Person} is away until {Until:yyyy-MM-dd});
你觉得怎么样?我确信代码在效率方面可以改进,但它确实有效!
我也使用类似的扩展方法,我喜欢它,我还在扩展方法中指定区域性信息,这在我的情况下是为系统固定的。
public static string Format(this string formatTemplate, params object[] args)
{
return string.Format(SysSettings.CultureInfo, formatTemplate, args);
}
用法:
return "date: {0:dd.MM.yyyy}'ntime: {1:mm:HH:ss}'nuser: {2} ({3})".Format(DateTime.Now, DateTime.Now, _user, _status);
这取决于您是单独编码还是有团队。在团队中,这是一个非常糟糕的主意,因为每个人都必须学习这种方法。
另一个问题是在格式中,字符串中的args意外包含索引错误的大括号,如{1}而不是{2}。这样,只要字符串不正确就会导致整个应用程序崩溃。我在日志记录中使用了类似的东西,并且不得不对FormatExceptions使用try-catch。