বিজোড় রিটার্ন সিনট্যাক্স স্টেটমেন্ট


106

আমি জানি এটি অদ্ভুত লাগতে পারে তবে ইন্টারনেটে এই বাক্যবিন্যাসটি কীভাবে অনুসন্ধান করতে হবে তা আমি জানি না এবং ঠিক এটির অর্থ কী তাও আমি নিশ্চিত নই।

সুতরাং আমি কিছু মোড়লিংকিউ কোড দেখেছি এবং তারপরে আমি এই পদ্ধতিটি লক্ষ্য করেছি

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 _();?


6
না মানে return _(); IEnumerable<TSource> _()?
অ্যালেক্স কে।

6
@ স্টিভ, আমি ভাবছি যে ওপি যদি এর return _(); IEnumerable<TSource> _()চেয়ে বেশি উল্লেখ করে yield return?
রব

5
আমি মনে করি তিনি এই লাইনটি বোঝালেন return _(); IEnumerable<TSource> _()। আসল রিটার্নের বিবৃতি না দিয়ে দেখতে যেভাবে দেখায় সে বিভ্রান্ত হতে পারে।
ম্যাটিউজ

5
@ আকাশকাভা ওপি বলেছে যে এখানে একটি বিজোড় বিবৃতি ছিল। দুর্ভাগ্যক্রমে, কোডটিতে দুটি রিটার্ন স্টেটমেন্ট রয়েছে । সুতরাং এটি বোঝা যায় যে লোকেরা বিভ্রান্ত হয়ে পড়ে যার সাথে সে উল্লেখ করছে।
mjwills

5
প্রশ্নটি সম্পাদনা করেছেন এবং আবারও বিভ্রান্তির জন্য দুঃখিত।
kuskmen

উত্তর:


106

এটি সি # 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;
            }
        }
    }

বর্তমান সি # সহ 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(); 

    }

কৌশলটি হল, _ () এটি ব্যবহারের পরে ঘোষণা করা হয়েছে, যা পুরোপুরি ঠিক আছে।

স্থানীয় ফাংশনগুলির আসল ব্যবহার

উপরের উদাহরণটি কেবল ইনলাইন পদ্ধতিটি কীভাবে ব্যবহার করা যেতে পারে তা কেবলমাত্র একটি প্রদর্শনের জন্য, তবে সম্ভবত আপনি যদি পদ্ধতিটি কেবল একবার শুরু করতে চলেছেন, তবে এটির কোনও লাভ নেই।

তবে উপরে উদাহরণস্বরূপ, ফোশি এবং লুয়ান মন্তব্যগুলিতে উল্লিখিত হিসাবে স্থানীয় ফাংশন ব্যবহার করার একটি সুবিধা রয়েছে। যেহেতু ফলন ফেরতের সাথে ফাংশন কার্যকর করা হবে না যতক্ষণ না কেউ এটির পুনরাবৃত্তি করে, এই ক্ষেত্রে স্থানীয় ফাংশনের বাইরের পদ্ধতি কার্যকর করা হবে এবং প্যারামিটারের বৈধতা কার্যকর করা হবে এমনকি যদি কেউ মানটিকে পুনরাবৃত্তি না করে তবেও।

আমরা পদ্ধতিতে বার বার কোড করেছি, আসুন এই উদাহরণটি দেখুন ...

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

4
@ZoharPeled ভাল .. পোস্ট কোড আছে ম ফাংশনের জন্য একটি ব্যবহার দেখান .. :)
রব

2
@ কলিনম এর একটি সুবিধা হ'ল বেনামে ফাংশন সহজেই তার 'হোস্ট' থেকে ভেরিয়েবল অ্যাক্সেস করতে পারে।
mjwills

6
আপনি কি নিশ্চিত যে সি #-স্পিকার এটিকে আসলে একটি বেনাম ফাংশন বলা হয়? এটির নাম _AnonymousFunctionবা ন্যায়বিচার রয়েছে বলে মনে হয় _, যখন আমি একটি আসল বেনাম ফাংশনটি এমন কিছু হওয়ার প্রত্যাশা করি (x,y) => x+y। আমি এটিকে স্থানীয় ফাংশন বলব, তবে আমি সি # পরিভাষায় অভ্যস্ত নই।
চি

12
স্পষ্ট করে বললে, যেহেতু কেউ এটি উল্লেখ করেছে বলে মনে হয় না, এই কোড স্নিপেট স্থানীয় ফাংশনটি ব্যবহার করছে কারণ এটি একটি পুনরাবৃত্তিকারী ( ফলনটি নোট করুন), এবং তাই অলসভাবে কার্যকর করে। স্থানীয় ফাংশন ব্যতীত আপনাকে প্রথমে মেনে নেওয়া দরকার যে ইনপুট বৈধতা প্রথম ব্যবহারের ক্ষেত্রে ঘটেছিল বা এমন একটি পদ্ধতি রয়েছে যা কেবল খুব অল্প কারণে প্রায় পড়ে থাকা অন্য কোনও পদ্ধতি দ্বারা ডাকা হবে।
ফোশি

6
@ কলিনম কুকসমান পোস্ট করা উদাহরণটি হ'ল এটি অবশেষে বাস্তবায়িত হওয়ার মূল কারণগুলির মধ্যে একটি - যখন আপনি কোনও ফাংশন তৈরি করেন yield return, গণ্যমানের প্রকৃত গণনা না করা অবধি কোনও কোড কার্যকর করা হয় না। এটি অনাকাঙ্ক্ষিত, যেহেতু আপনি যেমন এখনই আর্গুমেন্টগুলি যাচাই করতে চান। সি # তে এটি করার একমাত্র উপায় হ'ল পদ্ধতিটি দুটি পদ্ধতিতে আলাদা করা - একটির সাথে yield returnএবং অন্যটি ছাড়া। ইনলাইন পদ্ধতিগুলি আপনাকে অভ্যন্তরyield ব্যবহারের পদ্ধতিটি ঘোষণা করতে অনুমতি দেয় , বিশৃঙ্খলা এড়ানো এবং এমন কোনও পদ্ধতির সম্ভাব্য অপব্যবহার এড়ানো যা এর পিতামাতার সাথে কঠোরভাবে অভ্যন্তরীণ এবং পুনরায় ব্যবহারযোগ্য নয়।
লুয়ান

24

সহজ উদাহরণ বিবেচনা করুন

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

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

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

_() রিটার্নের বিবৃতি সম্বলিত পদ্ধতিতে ঘোষিত একটি স্থানীয় ফাংশন।


3
হ্যাঁ আমি স্থানীয় ফাংশন সম্পর্কে জানি এটি ফর্ম্যাটিং যা আমাকে বোকা বানিয়েছিল ... আশা করি এটি স্ট্যান্ডআর্ট হয়ে উঠবে না।
কুস্কমেন

20
আপনি কি একই লাইনে শুরু ফাংশন ঘোষণা বলতে চান? যদি তাই হয় তবে আমি একমত, এটি ভয়াবহ!
স্টুয়ার্ট

3
হ্যাঁ, এটাই আমি বোঝাতে চাইছিলাম
kuskmen

9
নামকরণ বাদে এটি আন্ডারস্কোর হিসাবে ভয়াবহ
আইসপিকল

1
@ আকাশকাবা: প্রশ্নটি বৈধ সি # কিনা তা নয়, তবে কোডটি বোঝা সহজ (এবং তাই এটি বজায় রাখা সহজ এবং পড়তে আগ্রহী) এই জাতীয় ফর্ম্যাট করার সময় কিনা। ব্যক্তিগত পছন্দগুলি ভূমিকা পালন করে তবে আমি স্টুয়ার্টের সাথে একমত হই।
পিজেট্রাইল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.