Odd return syntax statement

后端 未结 2 1163
刺人心
刺人心 2020-12-02 12:57

I know this may sound strange but I don\'t know even how to search this syntax in internet and also I am not sure what exactly means.

So I\'ve watched over some More

相关标签:
2条回答
  • 2020-12-02 13:24

    Consider the simpler example

    void Main()
    {
        Console.WriteLine(Foo()); // Prints 5
    }
    
    public static int Foo()
    {
        return _();
    
        // declare the body of _()
        int _()
        {
            return 5;
        }
    }
    

    _() is a local function declared within the method containing the return statement.

    0 讨论(0)
  • 2020-12-02 13:36

    This is C# 7.0 which supports local functions....

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

    Current C# with 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(); 
    
        }
    

    The trick is, _() is declared after it is used, which is perfectly fine.

    Pratical use of local functions

    Above example is just a demonstration of how inline method can be used, but most likely if you are going to invoke method just once, then it is of no use.

    But in example above, as mentioned in comments by Phoshi and Luaan, there is an advantage of using local function. Since function with yield return will not be executed unless someone iterates it, in this case method outside local function will be executed and parameter validation will be performed even if no one will iterate the value.

    Many times we have repeated code in method, lets look at this example..

      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... 
      }
    

    I could optimize this with...

      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... 
      }
    
    0 讨论(0)
提交回复
热议问题