nima uchun bu pastga tushish C # da muvaffaqiyatsiz tugadi?

Quyidagi kabi asosiy sinf va türetilmiş bir sinf bor

 public class BaseClass
{
    public int No { set; get; }
}

public class Derived : BaseClass
{
    public string Name { set; get; }
}

Men asosiy sinfning namunasini yaratganimda va uni toifadagi sinfga pastga tushirishni xohlasam, InvalidCastOperation funksiyasini qaytaradi.

class Program
{
    static void Main( string[] args )
    {
        BaseClass bas = new BaseClass();
        Derived derived = (Derived)bas;//invalid cast operation. why?
        System.Console.WriteLine();
    }
}

Nima uchun bu ishlamayapti? va bu so'rovni bajarish uchun echim kerakmi?

1
Buni upcasting deb atash kerak.
qo'shib qo'ydi muallif Sinatr, manba
Base sinfni ishga tushirasiz va uni tovarlar sinfiga ko'chirishga urinasiz. Base sinfda toifadagi sinf haqida hech qanday ma'lumot yo'q va u ham derivativ sinfi bilan bog'liq xususiyatlarga ega emas. Shuning uchun buni qilish mumkin emas. Derivativ sinfi asosiy sinfga o'tkazilishi mumkin, ammo aksincha, bu mumkin emas. Bu erda erishmoqchi bo'lgan narsalarni tushuntirsangiz yaxshi bo'ladi.
qo'shib qo'ydi muallif Brijesh, manba
Barcha Derivativlar BaseClass, ammo barcha BaseClasslar Tillardir
qo'shib qo'ydi muallif Nkosi, manba
qo'shib qo'ydi muallif Robin Hames, manba

8 javoblar

Buning uchun Derived misolini yaratishingiz kerak, chunki siz uni qaytarib olishni xohlaysiz:

BaseClass bas = new Derived();

base baseClass turi sifatida e'lon qilingan bas misolini derived :

Derived derived = (Derived)bas;
8
qo'shib qo'ydi

Batafsil mazmunli nomlardan foydalaning:

class Fruit { }
class Apple : Fruit { public int PitCount; }

Fruit f = new Fruit();//f is just some undetermined Fruity thing
Apple a = (Apple) f;  //why would it be an Apple? Where would PitCount come from?

Ushbu turdagi xatolarning oldini olish uchun meva abstrakt ni yaratishdir f , turli xil manbalardan kelib chiqadigan bo'lsa, yanada keng tarqalgan foydalanish tartibi quyidagilar:

if (f is Apple)
{
    Apple a = (Apple) f;//now it will work
}
6
qo'shib qo'ydi
yaxshi misol. ularning do'stlari uchun rahmat
qo'shib qo'ydi muallif Xeta7, manba

BaseClass misolini yaratdingiz va uni Derived ga ko'chirishga harakat qiling. Albatta, bu muvaffaqiyatsiz. Har Derived ham bir BaseClass , lekin, albatta, boshqa yo'l emas.

Agar qilgan bo'lsangiz

BaseClass bas = new Derived();
Derived derived = (Derived) bas;

masalan, aslida aslida Derived misolidir.

5
qo'shib qo'ydi

Meroslikka oid qoidalar quyidagilardir:

  • Boshlang'ich sinfning har bir nusxasi ham asosiy sinfning misolidir.
  • Boshqa yo'l atrofida qo'llanilmaydi. Har bir tayanch klassi ham ma'lum bir tafovutli sinf emas. Bu oddiy sinfning namunasi (masalan, sizning namunangizda) yoki bazadan olingan boshqa bir sinfning namunasi bo'lishi mumkin.

Sizning namunangizni tuzatish uchun:

BaseClass bas = new Derived();
Derived derived = (Derived)bas;//or better: = bas as Dervied
2
qo'shib qo'ydi
Nima uchun bash-ni Derived sifatida ko'rishingiz kerak? Derived ning bir nusxasi aslida bilaman bas , ishonchli translatsiyaga ehtiyoj yo'q va null .
qo'shib qo'ydi muallif HimBromBeere, manba
va -bo'limni xavfsiz ravishda tekshirish foydasizdir, ni -cast sifatida ishlatish yaxshi bo'ladi va null ni tekshiring yoki agar tip-tekshirishni keyin to'g'ridan-to'g'ri quyishdan foydalaning. Biroq, bu savolning doirasi yoki bu javobdan tashqari, faqatgina bir chetga.
qo'shib qo'ydi muallif HimBromBeere, manba
Bu holatda ha - bu muhim emas. Faqatgina istisno qilishning o'rniga men xavfsiz tashlashni (va tekshirishni tekshirishni) afzal ko'rmoqchiman.
qo'shib qo'ydi muallif Matthias247, manba
Men shuni aytdim. To'qimalar ortiqcha null tekshirish men uchun tekshirishning bir shakli hisoblanadi. - operatori boshqa - holatga bog'liq bo'lgan holatga bog'liq.
qo'shib qo'ydi muallif Matthias247, manba

Buni yozganda nimani kutmoqdasiz:

object o = new object();
MyClass m = (MyClass) o;

Albatta, bu o kodi MyClass haqida hech qanday ma'lumotga ega bo'lmagan holda ob'ekt hisoblanadi. Ayniqsa o kodi MyClass da belgilangan maydonlarni va xususiyatlarni belgilashni bilmaydi, shuning uchun o yaratishda faqat ob'ekt , MyClass uchun emas, balki. Xo'sh, agar bu o'yinda muvaffaqiyat qozona olsak, nima bo'ladi? Faqat ob'ekt ning bir nusxasi bor edi, u faqat a'zolar bilan, uni MyClass ga ko'chirib olib, uning a'zolarining hech biri boshlanmaganligi sababli, noto'g'ri nusxasini oling.

Boshqacha aytganda: MyClass ning har bir nusxasi ob'ekti , lekin ob'ekt emas , bir MyClass .

Sizda bir necha imkoniyatlar mavjud.

  1. Create an instance of your derived class

    BaseClass b = new Derived();
    
  2. Create a copy-constructor that creates a new instance of Derived based on the current instance of BaseClass:

    public class BaseClass
    {
        public int MyProperty { get; set; }
    }
    
    public class Derived : BaseClass
    {
        public string AnotherProperty { get; set;}
    
        public Derived(BaseClass b)
        {
            this.MyProperty = b.MyProperty;
            this.AnotherProperty = "MyValue";
        }
    }
    
  3. Use some reflction-based code that creates a new instance of Derived and copies all properties and fields from an existing instance of BaseClass. This is quite similar to 2. but avoids that you have to set the members yourself in the code.

1
qo'shib qo'ydi

Ob'ektni türetilen turdagi emasligi sababli, asosiy obyektni türetilen turga surata olmaysiz. Boshqacha qilib aytganda, DerivedType obyekti merosning tabiati bo'yicha BaseType dir. Orqaga ham to'g'ri emas - BaseType , albatta, DerivedType emas.

Buni o'ylab ko'ring. Buni qilishingiz mumkin:

Square a = new Square();
Shape b = (Shape)a;

chunki meros huquqiga ega bo'lishi mumkin - kvadrat shakli shakli.

Biroq, buni qilishga harakat:

Shape a = new Shape();
Square b = (Square)a;

chunki kvadrat shakli bo'lsa ham, xuddi uchburchak, aylana, parallelogram yoki trapezoid deb aytiladi. Hech qanday tasodifiy shakldan foydalana olmaysiz va ularning har qanday bo'lishi mumkinligini aytish mantiqiy emas, chunki bularning barchasi all , bu aniq emas - kvadrat uchburchak emas va hech qachon bo'lmaydi.

1
qo'shib qo'ydi

Buning sababi, asosan, sizning TURNED EXTENDS BaseClass uchun berilganligi sababli javob berish. Buning ma'nosi, sizning BaseClass -ga qo'shilmagan narsalarga (funksiyalar, joylar ...) qo'shiladi. Buning uchun kompilyator sehrli tarzda ushbu kengaytmalarni o'z ichiga olgan yangi namunani yaratishi va keyin uni o'zingiz/o'zgarmaydiganga tayinlashi kerak bo'ladi.

Har narsalarni tozalash. Ob'ekt namunasini yaratganingizda, u turdagi barcha a'zolarni yaratadi (asosiy metadata bilan birga). Va BaseClass ushbu turdagi yaratilganligi uchun Derived haqida hech narsa bilmaydi. Derived obyekti tomonidan kiritilgan yangi mulk haqida hech narsa eslatib o'tilmaydi.

// BaseClass :
//  - metadata of this type and System.Object ( because every object derives from System.Object in C# )
//  - field info of "No" property's backing field 
//  - property info "No" property

// Derived :
//  - metadata of this type and BaseClass type
//  - field info of "Name" property's backing field 
//  - property info "Name" property
0
qo'shib qo'ydi

Derived siz BaseClass ni kengaytiradi.

Siz bitta kod bilan Basclass ni yaratasiz.

Buni Derived -ga tashlashni xohlaganingizda Name xususiyati yaratilmagan (ya'ni gapirish)

Agar sinab ko'rsangiz

 Derived derived = new Derived();
 BaseClass bas =(BaseClass)derived;
 System.Console.ReadLine();

bu derivat bazani kengaytirishi sababli ishlaydi, shuning uchun derivat yaratilganda Name va BaseClass uchun No kodi ham o'zgaruvchining nomi.

O'zgarishlarni o'zgartirayotganingizda translatsiya qo'shish mumkin emas. U erda bo'lishni kutadi, lekin u emas.

0
qo'shib qo'ydi