[C#] 로컬 함수 vs Lambda C # 7.0

C # 7.0 의 새로운 구현 을보고 있는데 로컬 함수를 구현했다는 것이 흥미 롭지 만 람다 식보다 로컬 함수가 선호되는 시나리오와 두 가지의 차이점은 무엇인지 상상할 수 없습니다.

람다는 anonymous함수이지만 로컬 함수는 아니지만 함수는 람다 식보다 이점이있는 실제 시나리오를 파악할 수 없습니다.

어떤 예라도 대단히 감사하겠습니다. 감사.



답변

이것은 C # 디자인 미팅 노트에서 Mads Torgersen이 로컬 기능을 처음 논의한 곳에서 설명했습니다 .

도우미 기능이 필요합니다. 단일 함수 내에서만 사용하고 있으며 포함하는 함수의 범위에 속하는 변수 및 유형 매개 변수를 사용합니다. 반면에 람다와는 달리 람다와는 일등 객체가 필요하지 않으므로 델리게이트 유형을 지정하고 실제 델리게이트 객체를 할당 할 필요가 없습니다. 또한 재귀 적이거나 일반적인 것이거나 반복자로 구현하기를 원할 수 있습니다.

더 확장하면 장점은 다음과 같습니다.

  1. 공연.

    람다를 만들 때는 델리게이트를 만들어야하는데,이 경우 불필요한 할당입니다. 로컬 함수는 실제로 함수일 뿐이며 델리게이트가 필요하지 않습니다.

    또한 로컬 함수는 로컬 변수를 캡처 할 때보다 효율적입니다. 람다는 일반적으로 변수를 클래스로 캡처하는 반면 로컬 함수는을 사용하여 전달되는 struct를 사용하여 ref할당을 다시 피할 수 있습니다.

    또한 로컬 함수 호출이 저렴하고 인라인 될 수 있으므로 성능이 더욱 향상 될 수 있습니다.

  2. 로컬 함수는 재귀적일 수 있습니다.

    람다는 재귀 적 일 수도 있지만 null, 대리자 변수에 할당 한 다음 람다에 할당 하는 어색한 코드가 필요합니다 . 로컬 함수는 자연스럽게 재귀적일 수 있습니다 (상호 재귀 적 포함).

  3. 로컬 기능은 일반적 일 수 있습니다.

    람다는 구체적인 유형의 변수에 할당해야하기 때문에 일반이 될 수 없습니다 (해당 유형은 외부 범위의 일반 변수를 사용할 수 있지만 동일하지는 않습니다).

  4. 로컬 함수는 반복자로 구현할 수 있습니다.

    Lambdas 는 yield return(and yield break) 키워드를 사용하여 IEnumerable<T>반환 함수 를 구현할 수 없습니다 . 지역 기능이 가능합니다.

  5. 로컬 기능이 더 좋아 보입니다.

    이것은 위의 인용문에서 언급되지 않았으며 개인적인 편견 일 수도 있지만 일반적인 함수 구문은 람다를 대리자 변수에 할당하는 것보다 낫다고 생각합니다. 지역 기능도 간결합니다.

    비교:

    int add(int x, int y) => x + y;
    Func<int, int, int> add = (x, y) => x + y;
    

답변

svick의 큰 대답 외에도 로컬 함수 에는 또 다른 이점이
있습니다 return. 명령문 후에도 함수의 어느 곳에서나 정의 할 수 있습니다 .

public double DoMath(double a, double b)
{
    var resultA = f(a);
    var resultB = f(b);
    return resultA + resultB;

    double f(double x) => 5 * x + 3;
}


답변

로컬 기능을 테스트하는 방법이 궁금하다면 JustMock에 기능이 있는지 확인 해야합니다. 테스트 할 간단한 클래스 예제는 다음과 같습니다.

public class Foo // the class under test
{ 
    public int GetResult() 
    { 
        return 100 + GetLocal(); 
        int GetLocal () 
        { 
            return 42; 
        } 
    } 
}

다음은 테스트 모습입니다.

[TestClass] 
public class MockLocalFunctions 
{ 
    [TestMethod] 
    public void BasicUsage() 
    { 
        //Arrange 
        var foo = Mock.Create<Foo>(Behavior.CallOriginal); 
        Mock.Local.Function.Arrange<int>(foo, "GetResult", "GetLocal").DoNothing(); 

        //Act 
        var result = foo. GetResult(); 

        //Assert 
        Assert.AreEqual(100, result); 
    } 
} 

다음은 JustMock 설명서에 대한 링크 입니다.

부인 성명. 저는 JustMock을 담당하는 개발자 중 한 사람입니다 .


답변

더 긴 실행 방법을 다룰 때 가비지 수집 압력을 피하기 위해 인라인 함수를 사용합니다. 주어진 시세 기호에 대해 2 년 또는 시장 데이터를 얻고 싶다고 가정하십시오. 또한 필요한 경우 많은 기능과 비즈니스 로직을 포장 할 수 있습니다.

하나는 서버에 대한 소켓 연결을 열고 이벤트를 이벤트에 바인딩하는 데이터를 반복하는 것입니다. 클래스가 설계된 것과 같은 방식으로 생각할 수 있습니다. 단 하나의 기능에 대해서만 작동하는 헬퍼 메소드를 작성하는 것은 아닙니다. 아래는 이것이 어떻게 보일지에 대한 샘플입니다. 변수를 사용하고 있으며 “helper”메서드가 마지막에 있습니다. 마지막으로 Exchange 클래스가 외부 / 주입 된 경우 이벤트 처리기를 멋지게 제거합니다. 보류중인 이벤트 처리기가 등록되지 않았습니다.

void List<HistoricalData> RequestData(Ticker ticker, TimeSpan timeout)
{
    var socket= new Exchange(ticker);
    bool done=false;
    socket.OnData += _onData;
    socket.OnDone += _onDone;
    var request= NextRequestNr();
    var result = new List<HistoricalData>();
    var start= DateTime.Now;
    socket.RequestHistoricalData(requestId:request:days:1);
    try
    {
      while(!done)
      {   //stop when take to long….
        if((DateTime.Now-start)>timeout)
           break;
      }
      return result;

    }finally
    {
        socket.OnData-=_onData;
        socket.OnDone-= _onDone;
    }


   void _OnData(object sender, HistoricalData data)
   {
       _result.Add(data);
   }
   void _onDone(object sender, EndEventArgs args)
   {
      if(args.ReqId==request )
         done=true;
   }
}

아래에 언급 된 바와 같은 장점을 볼 수 있습니다. 여기서 샘플 구현을 볼 수 있습니다. 이점을 설명하는 데 도움이되기를 바랍니다.


답변