문제

방금 vs2008을 설치했으며 Lambda 또는 대표 (또는 조합)로 해결할 수있는 문제를 해결했습니다.

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

문제는 때로는 문자열에 두 가지 다른 값이 포함되어 있는지 확인해야한다는 것입니다. 때로는 세 가지 값을 확인해야 할 수도 있습니다.

따라서 내가 제안하는 것은 "!

다음과 같은 다른 기능을 쓸 수 있습니다.

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 가지 다른 값과 비교할 때 이러한 기능 중 하나에 대의원을 작성한 다음이를 readData () 메소드로 전달하십시오.

나는 대표자들에게는 매우 단서가 없으며, 이것이 람다에 적합한 장소처럼 보이는지 확실하지 않지만 무언가가 나에게 말하고 있습니다.

호출 코드는 다음과 같습니다.

            // 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);
    }
도움이 되었습니까?

해결책

술어 기능을 찾고있는 것 같습니다. 수표를 하드 코딩하는 대신 수표를 수행 할 수있는 것보다 대의원을 매개 변수로 사용하십시오.

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

그런 다음 적절한 대의원을 생성하고 전달하는 몇 개의 포장지를 만들 수 있습니다.

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

임의의 터미네이터 수를 기반으로 한 대의원을 즉시 구축 할 수도 있습니다.

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

다른 팁

한 가지 옵션은 readData () 메소드를 과부하하는 것입니다. 확인하는 값이 포함 된 문자열 배열을 가져 오는 것입니다. 사용 확장 방법, 당신은 contain ()을 확장하여 문자열 배열을 가져갈 수 있습니다.

readData () 메소드는 다음과 같습니다.

private string ReadData(TcpClient s, string[] terminators) {
    // 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(terminators));

    return sb.ToString();
}

continates () 메소드 확장자는 다음과 같습니다.

public static bool Contains ( this String str , String[] testValues )
{
    foreach ( var value in testValues )
    {
        if ( str.Contains( value ) )
            return true;
    }
    return false;
}

이 구현은 테스트 할 다양한 문자열이있을 때마다 새로운 술어를 만들 필요가 없습니다.

Lambdas의 구문은 나 자신 (그리고 내 팀의 나머지 부분)에 대해 다소 외국이기 때문에 나는 약간 다른 해결책을 가졌다. 위의 .Any () 함수에서 수정 될 때 .all ()의 구문을 알 수 없었습니다.

목록의 모든 터미네이터가 발견되도록 .all () 기능도 필요했습니다. 그래서 나는 다음과 같은 것과 같은 것으로 끝났습니다.

delegate bool Predicate (string s, params [] string terminators);

bool HasAll(string s, params string [] terminators) {
    foreach (var t in terminators) {
       if (!s.contains(t)) return false;
    }
    return true;
}

bool HasAny(string s, params string [] terminators) {
    foreach (var t in terminators) {
        if (s.contains(t)) return true;
    }
    return false;
}
// Just looking now, I could also pass in a bool to switch between the two and remove one of these functions. But this is fairly clear


string ReadData(TcpClient sock, Function predicate, params [] string terminators) {
    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.ToString(), terminators);

    return sb.ToString();
}

그런 다음 호출 코드는 다음과 같습니다.

private void someFunc() 
{
    Predicate any = new Predicate(HasAny);
    Predicate all = new Predicate(HasAll);
    String response;

    // Check all strings exist
    response = ReadData(this.sock, all, "(", ")", "->")
    if (all(response, "(", ")", "->")
        SendData(this.sock, ...);

    // Check any string exists
    response = ReadData(this.sock, any, "Hi", "Hey", "Hello");
    if (any(response, "Hi", "Hey", "Hello"))
       SendData(this.sock, ...);
}

아마도 null 검사를 [모든 | all] 함수에 추가하고, do를 반대로 반전시키고, 파라를 복제하는 대신 응답을 확인하십시오! = null을 확인하십시오. 이 솔루션은 내 모든 사용 사례에 적합하며 상당히 인간 읽을 수 있습니다. 내가 위에서 언급 한 작은 변경을하는 한.

이 모든 것이 저에게 강조 표시됩니다. 그래도 Lambda 표현을 배워야 할 필요성!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top