কেন প্রানিকেট <টি> এর পরিবর্তে ফানক <টি, বুল>?


210

এটি কেবল একটি কৌতূহল প্রশ্ন আমি ভাবছিলাম যে কারওরও উত্তর আছে কিনা:

.NET ফ্রেমওয়ার্ক ক্লাস লাইব্রেরিতে আমাদের উদাহরণস্বরূপ এই দুটি পদ্ধতি রয়েছে:

public static IQueryable<TSource> Where<TSource>(
    this IQueryable<TSource> source,
    Expression<Func<TSource, bool>> predicate
)

public static IEnumerable<TSource> Where<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate
)

তারা Func<TSource, bool>পরিবর্তে ব্যবহার করবেন না কেন Predicate<TSource>? মত মনে হয় Predicate<TSource>শুধুমাত্র দ্বারা ব্যবহৃত হয় List<T>এবং Array<T>যখন Func<TSource, bool>দ্বারা প্রায় কাছাকাছি সব ব্যবহার করা হয় Queryableএবং Enumerableপদ্ধতি এবং এক্সটেনশন পদ্ধতি ... যেটা নিয়ে কী খবর?


21
হ্যাঁ, এইগুলির বেমানান ব্যবহারগুলি আমাকেও পাগল করে।
জর্জ মাউয়ার

উত্তর:


170

যদিও Predicateএকই সময়ে List<T>এবং Array<T>net নেট .০.০ এ প্রবর্তন করা হয়েছে , .NET 3.5 থেকে বিভিন্ন Funcএবং Actionরূপগুলি পাওয়া যায়।

সুতরাং এই Funcপূর্বাভাসগুলি লিনকিউ অপারেটরগুলির মধ্যে ধারাবাহিকতার জন্য ব্যবহৃত হয়। .Net 3.5, ব্যবহার সম্পর্কে এর মতো Func<T>এবং গাইডলাইন রাজ্যের :Action<T>

নতুন লিনকিউ ধরণের ব্যবহার করুন Func<>এবং Expression<>কাস্টম প্রতিনিধি এবং পূর্বাভাসের পরিবর্তে


7
দুর্দান্ত, এর আগে এই গুল্ডলাইনগুলি কখনও দেখেনি =)
সুইভিশ

6
এটি উত্তর হিসাবে গ্রহণ করবে, যেহেতু এটির সবচেয়ে বেশি ভোট রয়েছে। এবং কারণ জন
স্কিটির

4
লিখিত হিসাবে এটি একটি উদ্ভট নির্দেশিকা। অবশ্যই এটিতে "নতুন LINQ প্রকারগুলি" Func <> "এবং" অ্যাকশন <> "[...]" ব্যবহার করুন should এক্সপ্রেশন <> সম্পূর্ণ ভিন্ন জিনিস।
জন স্কিটি 10

3
ভাল, আসলে আপনাকে এটি গাইডলাইনটির প্রসঙ্গে রাখতে হবে যা একটি লিনকিউ সরবরাহকারী লেখার বিষয়ে। হ্যাঁ, লিনকিউ অপারেটরগুলির জন্য, গাইডলাইনটি হ'ল ফানক <> এবং এক্সপ্রেশন <> এক্সটেনশন পদ্ধতির পরামিতি হিসাবে ব্যবহার করা। আমি সম্মত হই যে আমি
ফানক

আমি মনে করি স্কিটির মূল বক্তব্য হ'ল এক্সপ্রেশন <> কোনও গাইডলাইন নয়। এই ধরণেরটি সনাক্ত করতে এবং এটির সাথে আলাদা কিছু করার জন্য এটি একটি সি # সংকলক বৈশিষ্ট্য।
ড্যানিয়েল আরউইকার

116

আমি আগে এই ভেবেছি। আমি Predicate<T>প্রতিনিধি পছন্দ করি - এটি দুর্দান্ত এবং বর্ণনামূলক। তবে, আপনাকে এর ওভারলোডগুলি বিবেচনা করতে হবে Where:

Where<T>(IEnumerable<T>, Func<T, bool>)
Where<T>(IEnumerable<T>, Func<T, int, bool>)

এটি আপনাকে প্রবেশের সূচকের উপর ভিত্তি করে ফিল্টার করতে দেয়। এটি দুর্দান্ত এবং ধারাবাহিক, যদিও:

Where<T>(IEnumerable<T>, Predicate<T>)
Where<T>(IEnumerable<T>, Func<T, int, bool>)

হবে না


11
ভবিষ্যদ্বাণী করা <int, bool> কিছুটা কুৎসিত হবে - একটি প্রিডিকেট সাধারণত (কম্পিউটার বিজ্ঞানের আইএমই) একক মানের উপর পূর্বাভাস দেওয়া হয়। এটি অবশ্যই <পেয়ার <টি, ইন >> এর পূর্বাভাস হতে পারে তবে এটি এমনকি খারাপও নয় :)
জন স্কিটি

খুব সত্য ... হি। না, আমার ধারণা ফানক পরিষ্কার।
Svish

2
নির্দেশিকাগুলির কারণে অন্য উত্তর গ্রহণ করেছে। আমি যদিও একাধিক উত্তর চিহ্নিত করতে পারতাম! যদি আমি বেশ কয়েকটি উত্তর "খুব উল্লেখযোগ্য" বা "একটি ভাল পয়েন্টও
রেখেছি

6
এইচএম, কেবলমাত্র আমি দেখেছি যে আমি প্রথম মন্তব্যটি ভুলভাবে লিখেছি: পি আমার পরামর্শ অবশ্যই
প্রিডিকেট

4
@ জোনস্কিট আমি জানি এই প্রশ্নটি পুরানো এবং সমস্ত, তবে কী অদ্ভুত? Whereএক্সটেনশন পদ্ধতিতে প্যারামিটারের নাম predicate। হিহ = পি।
কনরাড ক্লার্ক

32

অবশ্যই Funcকোনও নির্দিষ্ট প্রতিনিধি ব্যবহারের পরিবর্তে আসল কারণ হ'ল সি # আলাদাভাবে ঘোষিত প্রতিনিধিদের সম্পূর্ণ ভিন্ন ধরণের হিসাবে গণ্য করে।

যদিও Func<int, bool>এবং Predicate<int>উভয়েরই অভিন্ন যুক্তি এবং রিটার্নের ধরণ রয়েছে তবে সেগুলি কার্যনির্বাহী নয়। সুতরাং যদি প্রতিটি লাইব্রেরি প্রতিটি প্রতিনিধি প্যাটার্নের জন্য নিজস্ব প্রতিনিধি প্রকারের ঘোষণা করে তবে ব্যবহারকারীরা "ব্রিজিং" প্রতিনিধিদের রূপান্তর সম্পাদন না করে যতক্ষণ না those গ্রন্থাগারগুলি হস্তক্ষেপ করতে সক্ষম হয় না।

    // declare two delegate types, completely identical but different names:
    public delegate void ExceptionHandler1(Exception x);
    public delegate void ExceptionHandler2(Exception x);

    // a method that is compatible with either of them:
    public static void MyExceptionHandler(Exception x)
    {
        Console.WriteLine(x.Message);
    }

    static void Main(string[] args)
    {
        // can assign any method having the right pattern
        ExceptionHandler1 x1 = MyExceptionHandler; 

        // and yet cannot assign a delegate with identical declaration!
        ExceptionHandler2 x2 = x1; // error at compile time
    }

ফানক ব্যবহারের জন্য প্রত্যেককে উত্সাহিত করে মাইক্রোসফ্ট আশা করছে যে এটি বেমানান প্রতিনিধি প্রকারের সমস্যা দূর করবে। প্রত্যেকের প্রতিনিধিরা একসাথে দুর্দান্ত খেলবেন, কারণ তাদের প্যারামিটার / রিটার্নের ধরণের ভিত্তিতে কেবল তাদের মিলবে।

এটি সমস্ত সমস্যার সমাধান করে না, কারণ Func(এবং Action) outবা refপ্যারামিটার থাকতে পারে না , তবে সেগুলি কম ব্যবহৃত হয়।

আপডেট: মন্তব্যগুলিতে সভিশ বলেছেন:

তবুও, ফানক থেকে প্রেডিকেট এবং পিছনে কোনও প্যারামিটারের ধরণটি স্যুইচ করা কি কোনও পার্থক্য বলে মনে হচ্ছে না? কমপক্ষে এটি এখনও কোনও সমস্যা ছাড়াই সংকলন করে।

হ্যাঁ, যতক্ষণ না আপনার প্রোগ্রামটি আমার Mainফাংশনের প্রথম লাইনে কেবল প্রতিনিধিদের জন্য পদ্ধতিগুলি বরাদ্দ করে । সংকলক নীরবে নতুন একটি প্রতিনিধি অবজেক্টে কোড উত্পন্ন করে যা পদ্ধতিতে এগিয়ে যায় forward সুতরাং আমার Mainফাংশনে, আমি কোনও সমস্যা সৃষ্টি না করেই x1ধরণের হয়ে উঠতে পারি ExceptionHandler2

তবে, দ্বিতীয় লাইনে আমি প্রথম প্রতিনিধিটিকে অন্য একটি প্রতিনিধিকে নিয়োগ করার চেষ্টা করি। এমনকি ভেবেছিল যে ২ য় প্রতিনিধি প্রকারের ঠিক একই প্যারামিটার এবং রিটার্নের ধরণ রয়েছে, সংকলক ত্রুটি দেয় CS0029: Cannot implicitly convert type 'ExceptionHandler1' to 'ExceptionHandler2'

সম্ভবত এটি আরও পরিষ্কার করে দেবে:

public static bool IsNegative(int x)
{
    return x < 0;
}

static void Main(string[] args)
{
    Predicate<int> p = IsNegative;
    Func<int, bool> f = IsNegative;

    p = f; // Not allowed
}

আমার পদ্ধতি IsNegativeনির্ধারণ করার জন্য একটি পুরোপুরি ভাল জিনিস pএবং f, ভেরিয়েবল যতদিন আমি তাই সরাসরি কি হিসাবে। তবে তারপরে আমি সেই ভেরিয়েবলগুলির মধ্যে একটিতে অন্যটির জন্য বরাদ্দ করতে পারি না।


তবুও, ফানক <টি, বুল> থেকে প্রেডিকেট <টি> এবং পিছনে কোনও প্যারামিটার ধরণের স্যুইচ করা কি কোনও পার্থক্য বলে মনে হচ্ছে না? কমপক্ষে এটি এখনও কোনও সমস্যা ছাড়াই সংকলন করে।
সুইভিশ

মনে হচ্ছে এমএস বিকাশকারীদের এগুলি একই চিন্তা করতে নিরুৎসাহিত করার চেষ্টা করছে। আমি ভাবছি কেন?
ম্যাট কোকাজ

1
প্যারামিটারের প্রকারটি স্যুইচিংয়ের ফলে কোনও পার্থক্য হয় যদি আপনি যে অভিব্যক্তিটি এটিতে পাঠাচ্ছেন তা পদ্ধতি কলের জন্য পৃথকভাবে সংজ্ঞায়িত করা হয়েছে, তারপরে এটি সংকলক দ্বারা অনুমান করা টাইপের পরিবর্তে হয় Func<T, bool>বা টাইপ করা হবে Predicate<T>
অ্যাডাম রাল্ফ

30

পরামর্শটি (3.5 এবং উপরে) হ'ল Action<...>এবং Func<...>- "কেন?" - একটি সুবিধা হ'ল " Predicate<T>" কেবল তখনই অর্থবহ, যদি আপনি "প্রিডিকেট" এর অর্থ কী তা জানেন - অন্যথায় আপনাকে স্বাক্ষর সন্ধানের জন্য অবজেক্ট-ব্রাউজার (ইত্যাদি) দেখতে হবে।

বিপরীতে Func<T,bool>একটি স্ট্যান্ডার্ড প্যাটার্ন অনুসরণ করে; আমি তাত্ক্ষণিকভাবে বলতে পারি যে এটি এমন একটি ফাংশন যা গ্রহণ করে Tএবং একটি ফেরত দেয় bool- কোনও পরিভাষা বোঝার দরকার নেই - কেবল আমার সত্য পরীক্ষাটি প্রয়োগ করুন।

"প্রিডিকেট" এর জন্য এটি ঠিক থাকতে পারে তবে আমি মানক করার চেষ্টাটির প্রশংসা করি। এটি সেই অঞ্চলে সম্পর্কিত পদ্ধতিগুলির সাথে অনেক সমতাও মঞ্জুরি দেয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.