c# - 使用 Lambda 和委托(delegate)进行重构

标签 c# .net refactoring delegates lambda

我刚刚安装了 VS2008,遇到了一个问题,我确信可以使用 lambda 或委托(delegate)(或组合!)来解决。

    private string ReadData(TcpClient s, string terminator)
    {
        // Reads a byte steam into a string builder until either data is unavailable or the terminator has not been reached
        var sb = new StringBuilder();
        do
        {
            var numBytesRead = s.GetStream().Read(byteBuff, 0, byteBuff.Length);
            sb.AppendFormat("{0}", Encoding.ASCII.GetString(byteBuff, 0, numBytesRead));
        } while (s.GetStream().DataAvailable && !sb.ToString().Contains(terminator));

        return sb.ToString();
    }

问题是,有时我需要检查字符串是否包含两个不同值中的任何一个。有时我可能需要检查它的三个值。

所以我的建议是将“!sb.ToString().Contains(terminator)”更改为传递到方法中的函数。

我可以编写不同的函数,例如:

private bool compare1(string s, string t) {
    return s.contains(t)
}

private bool compare2(string s, string t1, string t2) {
    return (s.compare(t1) or s.compare(t2)
}

// etc...

然后,当我想与 3 个不同的值进行比较时,为这些函数之一创建一个委托(delegate),然后将其传递给 ReadData() 方法。

对于委托(delegate),我一无所知,我不确定这是否适合放置 lambda,但有些东西告诉我它是。

调用代码是这样的:

            // Enter username .
        if (HasData(s,"login:"))
            SendData(s, switchUser + TelnetHelper.CRLF);

HasData 与 ReadData 相同,但返回的是 bool 值而不是字符串(我也想使用一些技巧将其分解为一个方法 - 但这是一个次要问题 - 不过请随时回答。

仅供引用:

     private bool HasData(TcpClient s, string terminator)
    {
        // Reads a byte steam into a string builder until either data is unavailable or the terminator has not been reached
        var sb = new StringBuilder();
        do
        {
            var numBytesRead = s.GetStream().Read(byteBuff, 0, byteBuff.Length);
            sb.AppendFormat("{0}", Encoding.ASCII.GetString(byteBuff, 0, numBytesRead));
        } while (s.GetStream().DataAvailable && !sb.ToString().Contains(terminator));

        return sb.ToString().Contains(terminator);
    }

最佳答案

听起来您正在寻找谓词函数。不要对检查进行硬编码,而是将委托(delegate)作为参数来进行检查

    private string ReadData(TcpClient s, Func<string,bool> predicate)
    {
        // Reads a byte steam into a string builder until either data is unavailable or the terminator has not been reached
        var sb = new StringBuilder();
        do
        {
            var numBytesRead = s.GetStream().Read(byteBuff, 0, byteBuff.Length);
            sb.AppendFormat("{0}", Encoding.ASCII.GetString(byteBuff, 0, numBytesRead));
        } while (s.GetStream().DataAvailable && !predicate(sb));

        return sb.ToString();
    }

然后你可以创建几个包装器,这些包装器只创建适当的委托(delegate)并将其传递下去

public bool HasData(TcpClient c, string terminator) {
  return HasData(c, (s) => s.Contains(terminator));
}

public bool HasData(TcpClient c, string t1, string t2) {
  return HasData(c, (s) => s.Contains(t1) || s.Contains(t2));
}

您甚至可以根据任意数量的终止符即时构建委托(delegate)

public bool HasData(TcpClient c, params string[] terminatorList) {
  return HasData(c, (s) => terminatorList.Where(x => s.Contains(x)).Any());
}

关于c# - 使用 Lambda 和委托(delegate)进行重构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/809945/

相关文章:

java - 我们可以重构这些方法吗?

python - 如何重构使用 argparse 的脚本以在另一个 Python 脚本中调用?

c# - WebBrowser 读取查看器代码而不是源代码

c# - ListViewItem IsSelected Binding - 适用于 WPF,但不适用于 WinRT

.net - 适用于 Windows 的网格托管

oop - 违反 SRP、Demeter 法则等的影响

c# - 实验性特征 "indexed members"是什么?

c# - 如何正确制作 byte[] 字段必填字段?

.net - 在 Silverlight 中将代码隐藏添加到资源字典时出现 xClassNotDerivedFromElement 错误

C# "deteriorating"列表?