كيف يمكنني تجنب الملاكمة/غير الملاكمة عند تمديد System.Object؟

StackOverflow https://stackoverflow.com/questions/2609054

سؤال

أنا أعمل على طريقة تمديد ينطبق فقط على الأنواع المرجعية. ومع ذلك ، أعتقد أنه في الوقت الحالي في الملاكمة وتفصل القيمة. كيف يمكنني تجنب ذلك؟

namespace System
{
    public static class SystemExtensions
    {
        public static TResult GetOrDefaultIfNull<T, TResult>(this T obj, Func<T, TResult> getValue, TResult defaultValue)
        {
            if (obj == null)
                return defaultValue;
            return getValue(obj);
        }
    }
}

مثال الاستخدام:

public class Foo
{
    public int Bar { get; set; }
}

في بعض الطرق:

Foo aFooObject = new Foo { Bar = 1 };
Foo nullReference = null;

Console.WriteLine(aFooObject.GetOrDefaultIfNull((o) => o.Bar, 0));  // results: 1
Console.WriteLine(nullReference.GetOrDefaultIfNull((o) => o.Bar, 0));  // results: 0
هل كانت مفيدة؟

المحلول

هذا ليس الملاكمة. أين تعتقد ذلك هو ملاكمة؟ إذا كان السبب في ذلك هو أنك نظرت إلى IL حول "==" ، فلا تدعها تخدعك - فإن JIT يحدد ما يجب القيام به هنا. لديها فرصة لإنشاء رمز أصلي مختلف لكل (T, TResult) زوج. في الواقع ، سيتم مشاركة الكود لجميع أنواع المرجع ، ويختلف لأنواع القيمة. لذلك سينتهي بك الأمر مع:

T = string, TResult = int (native code #1)
T = Stream, TResult = byte (native code #2)
T = string, TResult = byte (native code #2)
T = Stream, TResult = string (native code #3)

بعد قولي هذا ، إذا كنت ترغب في تقييد طريقة التمديد الخاصة بك على الأنواع المرجعية ، فقم بذلك:

public static TResult GetOrDefaultIfNull<T, TResult>
    (this T obj, Func<T, TResult> getValue, TResult defaultValue)
    where T : class

لا يزال هناك صندوق في IL ، لكن لا تقلق - لن يحدث أي ملاكمة بالفعل. بعد كل شيء ، ماذا يستطع يكون محاصرًا؟ أنت تقدم مرجعًا ، والمراجع نفسها ليست محاصرًا أبدًا - فقط قيم نوع القيمة محاصر.

نصائح أخرى

ببساطة ، لا يوجد شيء في هذا الرمز يتطلب الملاكمة. هناك نكون السيناريوهات التي لا يمكن تجنبها الملاكمة ، وهناك أيضًا رموز إمكانية إضافية لسد الفجوة بين أنواع القيمة/المرجع (constrained) في بعض الحالات.

ولكن ليس في هذه الحالة؛ لا فِعلي الملاكمة المطلوبة (يمكن لـ JIT إزالة بعض الحالات التي تشبه مربع - ولكن ليس كلها ، للأسف)

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