اكتب خطأ في الصب والمؤسس
-
01-10-2019 - |
سؤال
لدي فصلين
public class A
{
public A()
{
}
}
public class B:A
{
public B()
{
}
}
وهو الرمز الرئيسي كما يلي
A oa = new B();
B ob = new A();
هنا يجمع السطر 1 بنجاح بينما يعرض السطر 2 خطأ typecasting. لماذا يحدث هذا. ماذا يحدث بالضبط متى new B()
و new A()
يتم استدعاء؟
المحلول
ماذا يحدث بالضبط عندما يتم استدعاء New B () و New A ()؟
new A()
يبني كائن من النوعA
على كومة وإرجاع إشارة إليها.new B()
يبني كائن من النوعB
على كومة وإرجاع إشارة إليها.
هنا يجمع السطر 1 بنجاح بينما يعرض السطر 2 خطأ typecasting. لماذا يحدث هذا.
حيث B
فئات فرعية A
, ، إنه صالح للرجوع إليه من النوع A
للإشارة إلى كائن من نوع وقت التشغيل B
. بعد كل شيء، B
هي ببساطة "حالة خاصة" لـ A
.
ومع ذلك ، فإن العكس غير صحيح ، لأنه ليس كل شيء A
يمكن النظر في s B
س. على الرغم من أن هذا يتم فرضه بشكل صارم بواسطة C# آمنة نظام الكتابة حتى لو لم يكن هناك عدم توافق "حقيقي" ، فإن أسباب هذه القيود طبيعية. تخيل ، على سبيل المثال ، ذلك B
أعلن عقار public int Foo {get; set;}
. كيف تتوقع أن يتصرف هذا:
B ob = new A();
ob.Foo = 5;
هذا غير منطقي بوضوح: حقا الكائن الذي يشير إليه المرجع ليس له مثل هذا الملكية. وبالتالي ، فإن المترجم يحظر مثل هذه التركيبات.
تخيل الآن أنك غيرت رمزك إلى:
B b = (B)new A();
هنا ، أنت تخبر المترجم أن الكائن الذي تم إنشاؤه ، سوف ، في مدة العرض, ، كن قابلاً للتخصيص على مرجع من النوع B
. سيجمع هذا جيدًا ، ولكن بما أن التأكيد غير صحيح بشكل واضح ، فإن وقت التشغيل InvalidCastException
سيتم إلقاؤه.
لتلخيص ، نظام نوع C#(إذا تجاهلت dynamic
وبعض الحالات الخاصة) هي كلاهما ثابتة و آمنة: لن تتمكن بنجاح من علاج مثيل ملموس A
كما لو كان من النوع B
.
نصائح أخرى
لقد أعلنت متغيرًا من النوع B
, ثم حاولت تعيين قيمة النوع A
لذلك. لقد حددت B
ليكون نوعا من A
, ، لكن هذا لا يعني ذلك A
هي B
'س.
أعتقد أنه من مثل هذا:
class Animal { }
class Dog : Animal { }
class Cat : Animal { }
يمكنك ان تفعل Animal rex = new Dog()
, ، لأن كل الكلاب حيوانات ، ولكن ليس Dog fido = new Animal()
, ، لأن كل الحيوانات ليست كلاب.