我有一個代碼示例,其中一個MatchCollection似乎掛起程序時試圖用它與foreach。可以在嘗試迭代它時MatchCollection掛起程序嗎?
我使用的是類CSSParser解析CSS:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Helpers.Extensions;
namespace Helpers.Utils
{
public class CSSParser
{
private readonly Dictionary<string, Dictionary<string, string>>
_dict = new Dictionary<string, Dictionary<string, string>>();
private const string SelectorKey = "selector";
private const string NameKey = "name";
private const string ValueKey = "value";
private const string GroupsPattern
= @"(?<selector>(?:(?:[^,{]+)\s*,?\s*)+)\{(?:(?<name>[^}:]+)\s*:\s*(?<value>[^};]+);?\s*)*\}";
private const string CommentsPattern
= @"(?<!"")\/\*.+?\*\/(?!"")";
private readonly Regex _pattern
= new Regex(GroupsPattern, RegexOptions.IgnoreCase | RegexOptions.Multiline);
public CSSParser(string cssString)
{
var noCommentsString = Regex.Replace(cssString, CommentsPattern, "");
var matches = _pattern.Matches(noCommentsString);
foreach (Match item in matches)
{
var selector = item.Groups[SelectorKey].Captures[0].Value.Trim();
var selectorParts = selector.Split(',').Select(s=>s.Trim());
foreach(var part in selectorParts)
{
if (!_dict.ContainsKey(part))
_dict[part] = new Dictionary<string, string>();
}
var classNameCaptures = item.Groups[NameKey].Captures;
var valueCaptures = item.Groups[ValueKey].Captures;
var count = item.Groups[NameKey].Captures.Count;
for (var i = 0; i < count; i++)
{
var className = classNameCaptures[i].Value.TrimIfNotNull();
var value = valueCaptures[i].Value.TrimIfNotNull();
foreach(var part in selectorParts)
{
_dict[part][className] = value;
}
}
}
}
public IEnumerable<KeyValuePair<string,string>> LookupValues(string selector)
{
IEnumerable<KeyValuePair<string,string>> result
= new KeyValuePair<string,string>[]{};
if (_dict.ContainsKey(selector))
{
var subdict = _dict[selector];
result = subdict.ToList();
}
return result;
}
public string LookupValue(string selector, string style)
{
string result = null;
if (_dict.ContainsKey(selector))
{
var subdict = _dict[selector];
if (subdict.ContainsKey(style))
result = subdict[style];
}
return result;
}
}
}
,它工作正常,像這樣輸入:
[TestMethod]
public void TestParseMultipleElementNames()
{
const string css = @"h1, h2, h3, h4, h5, h6
{
font-family: Georgia, 'Times New Roman', serif;
color: #006633;
line-height: 1.2em;
font-weight: normal;
}
";
var parser = new CSSParser(css);
Assert.AreEqual("normal", parser.LookupValue("h4", "font-weight"));
}
但是當我用不含屬性的CSS串運行:
[TestMethod]
public void TestParseNoAttributesStyle()
{
const string css = @"
#submenu-container
{
}
";
var parser = new CSSParser(css);
Assert.IsFalse(parser.LookupValues("#submenu-container").Any());
}
程序掛在CSSParser的這一行上:
foreach (Match item in matches)
調試器停止標記當前正在執行的行,循環塊本身永遠不會到達。
爲什麼MatchCollection掛我的程序?
出於完整性:
namespace Helpers.Extensions
{
public static class StringExtension
{
public static string TrimIfNotNull(this string input)
{
return input != null ? input.Trim() : null;
}
}
}
我並不是Regex的專家,但是如果Regex引擎必須執行持續的lookahead和lookbehind操作,它可能會卡住或需要很長時間。設計你的正則表達式來最小化這些會有所幫助。也許正則表達式專家可以幫助你解決具體問題。 +1 =] – Sean
暫停調試器並查看堆棧以確定發生了什麼。選中「顯示外部代碼」查看所有內容。 – usr
a)像這樣的語言不應該*真正*用正則表達式解析。 b)爲什麼不[使用現成的東西](http://stackoverflow.com/q/512720/50776)?它可能會更快,更強大,並且讓您在項目中超前,而不是手工完成。 – casperOne