سؤال

وهذا هو مجرد مسألة فضول وأتساءل عما إذا كان أي شخص إجابة جيدة ل:

في مكتبة الفئات .NET Framework لدينا على سبيل المثال هاتين الطريقتين:

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 أساليب وطرق الإرشاد ... ما الأمر مع ذلك؟

هل كانت مفيدة؟

المحلول

وبينما تم إدخال Predicate في نفس الوقت أن List<T> وArray<T>، في صافي 2.0 Func مختلفة وAction المتغيرات تأتي من صافي 3.5.

وهكذا يتم استخدام تلك المسندات Func أساسا لالاتساق في مشغلي LINQ. اعتبارا من صافي 3.5، حول استخدام Func<T> وAction<T> في الدول التوجيهي :

<اقتباس فقرة>   

هل استخدام LINQ الجديدة أنواع Func<> و   Expression<> بدلا من العرف   المندوبين والمسندات

نصائح أخرى

ولقد تساءل هذا من قبل. أنا أحب مندوب 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>)

ولن يكون.

من المؤكد أن السبب الحقيقي لاستخدام Func بدلا من مندوب تحديدا هو أن C # يعامل أعلنت بشكل منفصل المندوبين إلى أنواع مختلفة تماما.

وعلى الرغم من Func<int, bool> وPredicate<int> لديهما حجة مماثلة والعودة أنواع، فهي ليست مهمة متوافق. حتى إذا أعلنت كل مكتبة نوعه مندوب الخاصة لكل نمط مندوب، فإن هذه المكتبات لن تكون قادرة على التعامل ما لم إدراج المستخدم "سد" المندوبين لأداء التحويلات.

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

وخلال تشجيع الجميع على استخدام وظائفها، ومايكروسوفت على أمل أن يؤدي ذلك إلى التخفيف من مشكلة أنواع مندوب غير المتوافقة. سوف المندوبين الجميع يلعب بشكل جيد معا، لأنها سوف تكون مجرد يقابل حتى على أساس المعلمة أنواعها / العائد.

وأنها لا تحل كل المشاكل، لأن FuncAction) لا يمكن أن يكون out أو ref المعلمات، ولكن تلك هي أقل شيوعا.

<القوي> تحديث: في تعليقات Svish يقول:

<اقتباس فقرة>   

ومع ذلك، تبديل نوع المعلمة من   ظائفها إلى المسند و   إلى الوراء، لا يبدو لجعل أي   فرق؟ على الأقل لا يزال يجمع   دون أي مشاكل.

نعم، ما دام البرنامج يعين فقط طرق للمندوبين، كما في السطر الأول من مهمتي Main. البرمجي بصمت الرمز إلى جديد كائن مندوب يقوم بإعادة توجيه إلى الأسلوب. حتى في بلدي وظيفة Main، أتمكن من تغيير x1 أن تكون من نوع ExceptionHandler2 دون أن تسبب مشكلة.

ولكن، على السطر الثاني وأنا أحاول أن تعيين مندوب الأول لمندوب آخر. حتى رأى 2ND نوع مندوب لديها بالضبط نفس المعلمة والعودة أنواع، المترجم يعطي 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، طالما أن أفعل ذلك مباشرة. ولكن بعد ذلك لا يمكن تعيين واحد من هذه المتغيرات إلى أخرى.

والنصيحة (في 3.5 وما فوق) هي استخدام Action<...> وFunc<...> - "لماذا؟" ل - ميزة واحدة هي أن "Predicate<T>" هو مفيد فقط إذا كنت تعرف ما هي "المسند" يعني - إلا كنت بحاجة الى ان ننظر في وجوه متصفح (الخ) للعثور على signatute

وعلى العكس من ذلك Func<T,bool> يتبع نمطا القياسية. أستطيع أن أقول على الفور أن هذا هو دالة التي تأخذ T وإرجاع bool - لا تحتاج إلى فهم أي المصطلحات - مجرد تطبيق اختباري الحقيقة

ل"المسند" هذا قد يكون حسنا، ولكن أنا أقدر محاولة لتوحيد. كما أنه يتيح الكثير من التكافؤ مع الطرق ذات الصلة في هذا المجال.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top