[c#] 이상한 반환 구문 문

나는 이것이 이상하게 들릴 수 있지만 인터넷 에서이 구문을 검색하는 방법도 모르고 정확히 무엇을 의미하는지 확실하지 않습니다.

그래서 몇 가지 MoreLINQ 코드를 살펴본 후이 방법을 발견했습니다.

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
    if (source == null) throw new ArgumentNullException(nameof(source));
    if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));

    return _(); IEnumerable<TSource> _()
    {
        var knownKeys = new HashSet<TKey>(comparer);
        foreach (var element in source)
        {
            if (knownKeys.Add(keySelector(element)))
                yield return element;
        }
    }
}

이 이상한 반환 진술은 무엇입니까? return _();?



답변

이것은 로컬 기능을 지원하는 C # 7.0입니다 ….

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
       this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
    {
        if (source == null) throw new
           ArgumentNullException(nameof(source));
        if (keySelector == null) throw
             new ArgumentNullException(nameof(keySelector));

        // This is basically executing _LocalFunction()
        return _LocalFunction();

        // This is a new inline method, 
        // return within this is only within scope of
        // this method
        IEnumerable<TSource> _LocalFunction()
        {
            var knownKeys = new HashSet<TKey>(comparer);
            foreach (var element in source)
            {
                if (knownKeys.Add(keySelector(element)))
                    yield return element;
            }
        }
    }

현재 C # Func<T>

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
       this IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
    {
        if (source == null) throw new
           ArgumentNullException(nameof(source));
        if (keySelector == null) throw
             new ArgumentNullException(nameof(keySelector));

        Func<IEnumerable<TSource>> func = () => {
            var knownKeys = new HashSet<TKey>(comparer);
            foreach (var element in source)
            {
                if (knownKeys.Add(keySelector(element)))
                    yield return element;
            }
       };

        // This is basically executing func
        return func();

    }

트릭은 _ ()가 사용 된 후에 선언된다는 것입니다.

로컬 기능의 실제 사용

위의 예는 인라인 메서드를 사용할 수있는 방법에 대한 데모 일 뿐이지 만 메서드를 한 번만 호출하려는 경우에는 쓸모가 없습니다.

그러나 위의 예에서 PhoshiLuaan의 주석에서 언급했듯이 로컬 함수를 사용하는 이점이 있습니다. yield return이있는 함수는 누군가가 반복하지 않으면 실행되지 않으므로이 경우에는 아무도 값을 반복하지 않더라도 로컬 함수 외부의 메서드가 실행되고 매개 변수 유효성 검사가 수행됩니다.

메서드에서 여러 번 코드를 반복했습니다.이 예제를 살펴 보겠습니다.

  public void ValidateCustomer(Customer customer){

      if( string.IsNullOrEmpty( customer.FirstName )){
           string error = "Firstname cannot be empty";
           customer.ValidationErrors.Add(error);
           ErrorLogger.Log(error);
           throw new ValidationError(error);
      }

      if( string.IsNullOrEmpty( customer.LastName )){
           string error = "Lastname cannot be empty";
           customer.ValidationErrors.Add(error);
           ErrorLogger.Log(error);
           throw new ValidationError(error);
      }

      ... on  and on...
  }

나는 이것을 다음과 같이 최적화 할 수있다.

  public void ValidateCustomer(Customer customer){

      void _validate(string value, string error){
           if(!string.IsNullOrWhitespace(value)){

              // i can easily reference customer here
              customer.ValidationErrors.Add(error);

              ErrorLogger.Log(error);
              throw new ValidationError(error);
           }
      }

      _validate(customer.FirstName, "Firstname cannot be empty");
      _validate(customer.LastName, "Lastname cannot be empty");
      ... on  and on...
  }


답변

더 간단한 예를 고려하십시오.

void Main()
{
    Console.WriteLine(Foo()); // Prints 5
}

public static int Foo()
{
    return _();

    // declare the body of _()
    int _()
    {
        return 5;
    }
}

_() return 문을 포함하는 메서드 내에서 선언 된 로컬 함수입니다.


답변