这是一个有点奇怪的问题,更像是一个我需要的任何实验,但我仍然对答案感到好奇:如果我有一个我提前知道永远不会改变但(大部分)组成的字符串重复部分,最好将字符串作为单个字符串对象,在需要时调用并完成它 - 或者我应该将字符串分解成代表重复部分的较小字符串并在需要时将它们连接起来?
让我举个例子:假设我们有一个天真的程序员想要创建一个用于验证 IP 地址的正则表达式(换句话说,我知道这个正则表达式不会按预期工作,但它有助于说明我所说的重复是什么意思部分,并为示例的第二部分节省了一些打字时间)。所以他写了这个函数:
private bool isValidIP(string ip)
{
Regex checkIP = new Regex("\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?");
return checkIP.IsMatch(ip);
}
现在我们的年轻程序员注意到他有“\d”、“\d?”和“\”。只是重复了几次。这给了他一个想法,即他既可以节省一些存储空间,又可以帮助提醒自己这对以后意味着什么。所以他重新制作了这个函数:
private bool isValidIP(string ip)
{
string escape = "\\";
string digi = "d";
string digit = escape + digi;
string possibleDigit = digit + '?';
string IpByte = digit + possibleDigit + possibleDigit;
string period = escape + '.';
Regex checkIP = new Regex(IpByte + period + IpByte + period + IpByte + period + IpByte);
return checkIP.IsMatch(ip);
}
第一种方法很简单。它只在程序指令中存储 38 个字符,每次调用函数时都会将这些字符读入内存。第二种方法将(我怀疑)两个长度为 1 的字符串和两个字符存储到程序指令中,以及将这四个字符串连接成不同顺序的所有调用。当程序被调用时,这会在内存中创建至少 8 个字符串(六个命名字符串,一个用于正则表达式前四个部分的临时字符串,然后是从前一个字符串创建的最终字符串 + 正则表达式的三个字符串)。第二种方法也恰好有助于解释正则表达式正在寻找什么 - 尽管不是最终正则表达式的样子。它还可以帮助重构,
再次,哪种方法会更好?它会像程序大小与内存使用之间的权衡一样简单吗? 当然,对于这样简单的事情,权衡充其量可以忽略不计,但是更大、更复杂的字符串呢?
哦,是的,一个更好的 IP 地址正则表达式是:
^(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)(\\.(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)){3}$
不会像例子一样好用,不是吗?