المشغل الضمني على الأنواع العامة
-
26-09-2019 - |
سؤال
هل هناك أي خطأ في استخدام مشغل ضمني مثل ما يلي:
//linqpad c# program example
void Main()
{
var testObject = new MyClass<int>() { Value = 1 };
var add = 10 + testObject; //implicit conversion to int here
add.Dump(); // 11
}
class MyClass<T>
{
public T Value { get; set; }
public static implicit operator T (MyClass<T> myClassToConvert)
{
return myClassToConvert.Value;
}
}
كنت أفكر في أنني يمكن أن أعامل كمثال للكائن كنوع قيمة بهذه الطريقة ، لكنني أرى أنه لم أر مثالًا على هذا الأمر ، فقد اعتقدت أنه ربما كان هناك سبب ليس لفعل شيء كهذا يمكن أن يشير شخص ما؟
في الكود الفعلي الخاص بي ، كنت أفكر في القيام بذلك كجزء من طبقة تجريد البيانات ، حتى أتمكن من إرجاع الكائنات بمعلومات تصف البيانات الأساسية ، ولكن السماح لرمز المنطق بمعاملته كنوع قيمة عندما يحتاج كل ما إلى معرفته هي القيمة ، وفي الوقت نفسه ، احتفظ بكل شيء لطيف وآمن مع الأدوية الجيلية.
المحلول
إذا كان كل ما يلي صحيحًا:
الكل القيم المحتملة الخاصة بك
MyClass<T>
الكتابة (بما في ذلكnull
إذا لم يكن نوع قيمة!) خريطة لقيمة صالحةT
المشغل الضمني لا يرمي أبدًا (ولا حتى ل
null
!)التحويل الضمني له معنى الدلالي ولا يربك المبرمج العميل
ثم لا حرج في هذا. طبعا انت يستطع افعل أيًا من هذه الأشياء الثلاثة ، لكنه سيكون تصميمًا سيئًا. على وجه الخصوص ، يمكن أن يكون من الصعب للغاية تصحيح المشغل الضمني الذي يرميه لأن المكان الذي يطلق عليه اسمه.
على سبيل المثال ، فكر في ذلك T?
ليس لديه تحويل ضمني إلى T
(أين T
هو ، بالطبع ، نوع القيمة). إذا كان هناك مثل هذا المشغل الضمني ، فسيتعين عليه رمي عندما T?
هو فارغ ، حيث لا توجد قيمة واضحة للتحويل null
لذلك سيكون من المنطقي أي نوع القيمة T
.
اسمحوا لي أن أعطي مثالاً حيث واجهت مشكلة في تصحيح مشكلة حيث ألقى المشغل الضمني:
public string Foo()
{
return some_condition ? GetSomething() : null;
}
هنا، GetSomething
أعاد شيء من النوع الذي كتبته والذي يحتوي على تحويل ضمني محدد من قبل المستخدم string
. لقد صنعت متأكد تماما الذي - التي GetSomething
لا يمكن أن تعود أبدا null
, ، ومع ذلك حصلت على NullReferenceException
! لماذا ا؟ لأن الرمز أعلاه هو ليس أي ما يعادل
return some_condition ? (string)GetSomething() : (string)null;
لكن من أجل
return (string)(some_condition ? GetSomething() : (Something)null);
الآن يمكنك أن ترى أين null
جاء من!
نصائح أخرى
هذا نمط رائع. فقط ضع في اعتبارك أنه من أجل استخدامه كمتغير من النوع T
, ، يجب عليك إما إلقاءها بشكل صريح T
, أو تعيينه لمتغير من النوع T
. سيتم إجراء فريق العمل تلقائيًا في مكالمات الطريقة وأشياء أخرى (مثل مثال الإضافة) التي تأخذ أ T
.