Dlaczego gdy przypiszę do typu object typ object to GetType() zwraca typ pierwszego obiektu?

0

Witam serdecznie. Nie potrafię tego rozbić na czynniki pierwsze. Napotkałem to podczas pisania aplikacji (oszczędziło mi to sporo kłopotów, że to tak działa, tylko dlaczego?)

string text = "abc";
object o1 = text;
 object o2 = o1;
MessageBox.Show(o2.GetType().ToString());

**text **jest typu string
Opakowujemy **text ** w object o nazwie **o1 **.
Opakowujemy **o1 ** w object o nazwie **o2 ** (i tutaj mogę popełnić błąd w myśleniu, bo może po prostu object cały czas przechowuje referencję do **text **?)
Skąd o2 wie co siedzi w o1? Bo MessageBox zwraca mi typ string

A tak drążąc dalej temat, jeżeli object potrafi rozpoznać jaki typ wartości przechowuje dlaczego trzeba rzutować i nie działa zwykłe:

string text2 = o2;
1

Nie opakowujemy, a rzutujemy - nie ma żadnych przekształceń

PS> tytuł by należało ująć:
gdy przypiszę do zmiennej typu object wartość typu object (co jest błędne)

0

No tak, bo przypisuję wartość typu string. Czyli object jest takim odpowiednikiem (void*) z cpp?

1
Grzegorz Świdwa napisał(a):

No tak, bo przypisuję wartość typu string. Czyli object jest takim odpowiednikiem (void*) z cpp?

Nie.

bardziej jest odpowiednikiem "wiodącego obiektu", z którego dziedziczy reszta - który nie występuje w czystym C++, ale hojnie we frameworkach C++, QObject w Qt, CObject w MFC itd...

Realna klasa, ma swoje nie za obszerne API
https://docs.microsoft.com/en-gb/dotnet/api/system.object?view=netcore-3.1

skoro jest to klasa, to każda zmienna typu Object jest referencją

0

Boże, czytałem już o tym i niestety nie ze zrozumieniem.
Taki przykład jest bardziej trafny?

        public class MyObject
        {
            public string GetType();
        }
        public class MyClass1 : MyObject
        {

        }
        public class MyClass2 : MyObject
        {

        }

Użycie

            MyClass1 c1 = new MyClass1();
            MyObject myObject1 = c1;
            MyObject myObject2 = myObject1;

To by się zgadzało. Tylko teraz tak. Skoro object jest klasą bazową dla wszystkich typów i nie ma on dostępu do "mojej klasy" (bo jest przecież klasą bazową), to skąd on wie, jaka konkretna klasa go dziedziczy (bo metoda GetType() pochodzi z object)? Mam nadzieję, że rozumiesz moją rozkminę ;)

0

W tych językach, inaczej niż w C++, to MUSI dziedziczyć, nie ma innego wyjścia.
W "tych" czyli Java / C#
Czyli wszystkie obiekty C# mają np. GetType()

Legalność podstawienia wynika z polimorfizmu.
GDYBY podstawienie było nielegalne (ale na Object jest zawsze legalne), nie skompiluje się / poleci wyjątek

W pseudokodzie Qt C++

Qobject & obj =  new QOsoba();
... = obj.objectName();

0

No tak, tylko skąd metoda w klasie bazowej wie, co zwrócić w metodzie GetType? Bo wszędzie czytałem, że klasa bazowa nie powinna mieć dostępu do klasy pochodnej

        public class MyObject
        {
            public string GetType()
            {
                 //Magia object, co tu się za kosmos znajduje. Skąd GetType() wie, że ma za chwilę zwrócić MyClass1. 
            }
        }
        public class MyClass1 : MyObject
        {

        }

Może podczas kompilacji coś się dzieje dziwnego czego nie rozumiem? Tylko mnie naprowadź na prawidłowy tok a resztę sam wyczytam

1
Grzegorz Świdwa napisał(a):

No tak, tylko skąd metoda w klasie bazowej wie, co zwrócić w metodzie GetType? Bo wszędzie czytałem, że klasa bazowa nie powinna mieć dostępu do klasy pochodnej

to jest ovveride z metody virtualnej, to tak działa

        public class MyObject
        {
            public string GetType()
            {
                 //Magia object, co tu się za kosmos znajduje. Skąd GetType() wie, że ma za chwilę zwrócić MyClass1. 
            }
        }

Może podczas kompilacji coś się dzieje dziwnego czego nie rozumiem? Tylko mnie naprowadź na prawidłowy tok a resztę sam wyczytam

Wiem, o co pytasz, GetType (chyba dobrze zgadujesz) powstaje "magicznie" podczas kompilacji (pisane z intuicji, a nie twardej wiedzy)

1

Jak rzutujesz referencję na typ bazowy np. String na Object ( Object jest typem bazowym wszystkich typów) to sama referencja się fizycznie nie zmienia . Jest dokładnie taka sama jak była.
Dlatego cały czas wychodzi ci typ String a nie jakbyś oczekiwał Object.
Przykład:

using System;

public class Test
{
   public static void Main()
   {
       A ob1 = new B();

       ob1.MetodaX();  
   }

   class A 
   {
       public void MetodaX()
       {
           Console.WriteLine("Klasa A");
       }
   }

   class B : A
   {
       new public void MetodaX()
       {
           Console.WriteLine("Klasa B");
       }
   }
}

Wynik na ekranie Klasa A .
Po rzutowaniu została wywołana metoda klasy bazowej A zamiast klasy B.
To kompilator C# podczas kompilacji wybrał, która metoda ma zostać wywołana na postawie samego kodu źródłowego programu.
Po skompilowaniu kodu źródłowego instrukcja :
ob1.MetodaX();
wygląda w kodzie IL tak:
callvirt instance void Test/A::MetodaX() .

Mam nadzieję , że teraz wszystko jest dla ciebie jasne już ;)

4

Tak tylko uściślę.

Zimny Krawiec napisał(a):

Jak rzutujesz referencję na typ bazowy np. String na Object ( Object jest typem bazowym wszystkich typów)

Nie, nie jest. Np. interfejsy, wskaźniki i "open" generic types nie dziedziczą z object.

to sama referencja się fizycznie nie zmienia . Jest dokładnie taka sama jak była.

Ja bym raczej powiedział, że referencji jest kilka, a wszystkie wskazują na ten sam obiekt w pamięci.

1
Grzegorz Świdwa napisał(a):
string text = "abc";
object o1 = text;
 object o2 = o1;
MessageBox.Show(o2.GetType().ToString());

Skąd o2 wie co siedzi w o1? Bo MessageBox zwraca mi typ string

Wnikanie w szczegóły implementacyjne, IL, uważam w tym temacie za zbędne.
Dostajesz "string", bo GetType zwraca prawdziwy typ obiektu, a nie typ referencji. I tyle :)

1

Rzeczywisty podział typów wygląda tak:

1 użytkowników online, w tym zalogowanych: 0, gości: 1