如何重构这些函数以促进代码重用?

时间:2009-08-17 16:48:50

标签: c# optimization delegates

几个星期前我写了这些辅助函数,我觉得我没有利用一些C#语言功能,这些功能会让我不再为其他类似的帮助者编写这些相同的循环。

任何人都可以建议我缺少什么吗?

public static IList<string> GetListOfLinesThatContainTextFromList(
        Stream aTextStream, IList<string> aListOfStringsToFind)
{
    IList<string> aList = new List<string>();

    using (var aReader = new StreamReader(aTextStream))
    {
        while (!aReader.EndOfStream)
        {
            var currLine = aReader.ReadLine();

            foreach (var aToken in aListOfStringsToFind)
                if (currLine.Contains(aToken))
                    aList.Add(currLine);
        }
    }

    return aList;
}

public static DataTable GetDataTableFromDelimitedTextFile(
        Stream aTextStream, string aDelimiter)
{
    var aTable = new DataTable();
    Regex aRegEx = new Regex(aDelimiter);

    using (var aReader = new StreamReader(aTextStream))
    {
        while (!aReader.EndOfStream)
        {
            // -snip-
            // build a DataTable based on the textstream infos
        }
    }

    return aTable;
}

3 个答案:

答案 0 :(得分:6)

我在这里使用作文。例如,对于第一个,首先将位读取线分开 - 并使其变得懒惰......

public static IEnumerable<string> ReadLines(Stream input)
{
    // Note: don't close the StreamReader - we don't own the stream!
    StreamReader reader = new StreamReader(input);
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        yield return line;
    }
}

(您可以在MiscUtil中找到功能更全面的版本。)

现在你可以使用LINQ来过滤不在合适的集合中的行(我使用HashSet而不是列表,除非它是一个非常短的列表):

var acceptedLines = new HashSet<string>();
// Populate acceptedLines here
var query = ReadLines(input).Where(line => acceptedLines.Contains(line))
                            .ToList();

填充DataTable时,可以使用相同的行读取方法。你需要小心 - 这是懒惰评估所以你需要保持流打开直到你完成阅读,然后自己关闭它。我更喜欢传递一些东西,让你得到 Stream(或TextReader),然后结束逻辑可以在ReadLines方法中。< / p>

答案 1 :(得分:1)

不幸的是,在这种情况下,我不确定重构在逻辑方面是否值得“节省”。您可以重构这一点,以便将您的using语句和while循环移动到一个单独的方法中,该方法使用Action<T>委托。这可以作为lambda表达式传递。这与List<T>.ForEach非常相似。

但是,我认为,在这种情况下,它会使您的代码不易维护。 using语句+ while循环虽然是重复的,但却是一个非常少量的共享代码。 lambda的复杂性可能不值得单个重复的循环结构。

如果涉及更多的共享逻辑,重构这可能是有意义的 - 但除了一个while循环(循环的内部不同),我认为你通过重构使它更复杂。如果您的某个案例需要以不同方式突破,这将特别重要 - 重构这可能会让您的生活更加复杂。

答案 2 :(得分:0)

我同意里德的观点,重构一点点代码可能不值得。但是,你似乎暗示这些代码将存在于几个地方。

我的开发方法是让应用程序正常运行。一旦它工作,通过单元测试,然后我将返回并重构。编码时的重构会冒更难维护代码的风险,因为你增加了一些复杂性,而且任何更多的重构都会继续增加更多。

但是,我已经使用Action委托来传递函数,进行重构,删除重复的代码,但是你的两个例子是完全不同的,因此使用Action委托不会获得任何东西。

如果你可以重做这些函数,那么唯一的区别就是循环中的处理,那么尝试使用Action委托可能是有意义的,但是,如果你想使用LINQ,那么我强烈要求Jon的建议(我当我打字回复时,当别人回应时,我喜欢它。)。