6

我有:

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})";
4

4 回答 4

3

好吧,一件坏事是,通过只有一个params object[]方法,您每次调用都强制进行额外的数组分配。

您可能会注意到string.Format有一系列重载用于获取少量参数(这些是非常常用的) - 我建议复制它们。

您的“理想”场景可以通过重写string.Format方法来完成,但您需要传入值,即

return "date: {date}\ntime: {...}\nuser: {_user} ({_status})"
     .Format(new { date = DateTime.Now, _user, _status });

(并使用您自己的自定义Format方法或类似的方法) - 但请注意,这会强制每次调用一个新的对象实例。

实际上,在某一时刻,单声道编译器有一个实验标志可以直接启用它。不知道有没有维护。

于 2013-07-12T09:47:18.820 回答
3

它不太符合您的理想,但这样的事情可能对您有用:

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

这对你来说怎么样?我确信代码可以在效率方面得到改进,但它确实有效!

于 2013-07-12T10:26:03.210 回答
2

我也使用类似的扩展方法,我喜欢它,我还在扩展方法中指定了文化信息,这在我的情况下是为系统固定的。

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);
于 2013-07-12T09:50:41.337 回答
1

这取决于您是单独编码还是有团队。在一个团队中,这是一个非常糟糕的主意,因为每个人都必须学习这种方法。

另一个问题是 Format with args 在字符串中意外包含带有错误索引的大括号,例如 {1} 而不是 {2}。这种方式只是坏字符串会使整个应用程序崩溃。我在日志记录中使用了类似的东西,并且不得不对 FormatExceptions 使用 try-catch。

于 2013-07-12T09:48:58.080 回答