String, konstruktor, nowy obiekt

0

Witam
Mam parę nurtujących pytań co do stringa.

Dlaczego nie moge tak utworzyc stringa ? chociaŻ jego konstruktor przyjmuje char[] ?

 
string a = new string("aaa");

W taki sposob nie ma problemu.

string a = new string('a', 1);
2

Dlaczego nie moge tak utworzyc stringa ? chociaŻ jego konstruktor przyjmuje char[] ?

Były programista C++?
Dlatego że to bez sensu - literał "asdf" jest już typu string, nie char[] (kompilator zresztą na pewno ci napisał o niezgodności typów)!

Przykład:

"asdf".Substring(1, 2)
2

Dlaczego nie moge tak utworzyc stringa ?

Dlatego, że string nie ma konstruktora przyjmującego parametr typu string.
Zresztą po co, skoro można po prostu

string a = "aaa";
0

Ok rozumiem po prostu "aa" to już string. A nie ma takiego czegoś jak automatycznie generowany konstruktor kopiujący?
Nie moge tez uzyskac info na temat listy inicjalizacyjnej konstruktora. Jest coś takiego ?

public Typ(int a_, int b_) : a(a_), b(b_)
{}
 

Co do

string a = "aaa";
 

Skoro a jest typem referencyjnym to w jaki to sposób działa ? Operator = jest przeładowany?

1

Proponuję zaopatrzyć się w podręcznik o C#, bo różnic pomiędzy tymi językami jest zbyt wiele, żeby wymienić je w tym wątku.

1
Bumcykowy napisał(a)

Ok rozumiem po prostu "aa" to już string. A nie ma takiego czegoś jak automatycznie generowany konstruktor kopiujący?
Nie moge tez uzyskac info na temat listy inicjalizacyjnej konstruktora. Jest coś takiego ?

Po co konstruktor kopiujący i lista inicjalizacyjna?

Co do

string a = "aaa";
 

Skoro a jest typem referencyjnym to w jaki to sposób działa ? Operator = jest przeładowany?

To jest element składni języka, nic nie jest przeładowane.

0

Czyli a jest typem referencyjnym, a później jemu jest przypisane tak jak by miejsce w pamięci gdzie znajduje się owy string ? Jezeli to są ewidentne podstawy to czemu w książce o tym nie ma?

2

C# powstał jako klon Javy, więc nie oczekuj jakiegoś mocnego podobieństwa do C++.

1

To string jest typem referencyjnym, a jest zmienną, która może tę referencję przechowywać (wskaźnik do obiektu na stercie zarządzanej).

1

Nie moge tez uzyskac info na temat listy inicjalizacyjnej konstruktora. Jest coś takiego ?

Jest, ale służy tylko do wywoływania innego konstruktora:

class Pochodna : Bazowa
{
  public Pochodna(int i)
      : base(i, 3)
  { }

  public Pochodna()
      : this(42)
  { }
}

Pola trzeba wypełniać normalnie w ciele konstruktora.

0
Bumcykowy napisał(a)

Czyli a jest typem referencyjnym, a później jemu jest przypisane tak jak by miejsce w pamięci gdzie znajduje się owy string ? Jezeli to są ewidentne podstawy to czemu w książce o tym nie ma?

W książce zapewne jest napisane, jak zadeklarować zmienną typu string i programiście więcej nie jest do szczęścia potrzebne. W C# nie trzeba używać gwiazdek i ampersandów.

0

Konstruktor kopiujący do kopiowania mi potrzebny. Co do listy bylem ciekaw czy jest tak samo jak w c++. Im więcej podobieństw tym lepiej dla mnie.
W C++ operator= i konstruktor kopiujący jest automatycznie generowany. Przy czym jest on użyteczny dopóki nie rezerwujemy pamięci i nie używamy wskaźników.

W książce zapewne jest napisane, jak zadeklarować zmienną typu string i programiście więcej nie jest do szczęścia potrzebne. W C# nie trzeba używać gwiazdek i ampersandów.

Po prostu lubię wiedzieć jak niektóre rzeczy działają.

Reasumując na temat string wiem co chciałem.
Dzieki za pomoc.

0

A kopiowanie ci jest potrzebne do…?

C# to nie C++. Ma w miarę podobną składnię, ale to jest inny język. Nie wszystko z C++ ma swoje bezpośrednie przełożenie na C#.

Niektórze rzeczy których „brakuje” tak naprawdę są, ale pod inną postacią. Niektórych wcale nie potrzeba. A inne znowu można ominąć pisząc kod inaczej.

0
Bumcykowy napisał(a)

Konstruktor kopiujący do kopiowania mi potrzebny. Co do listy bylem ciekaw czy jest tak samo jak w c++. Im więcej podobieństw tym lepiej dla mnie.

Na szczęście twórcy C# odcięli się od trzydziestoletnich błędów, więc podobieństw dużo nie ma.

W C++ operator= i konstruktor kopiujący jest automatycznie generowany. Przy czym jest on użyteczny dopóki nie rezerwujemy pamięci i nie używamy wskaźników.

W C# nie rezerwujemy pamięci i właściwie nie używamy wskaźników. A operator przypisania po prostu istnieje w języku, nie trzeba niczego generować.

0

A operator przypisania po prostu istnieje w języku, nie trzeba niczego generować.

A o czym ja pisałem ? Skoro generuje go kompilator to on już jest do naszego użytku, my go możemy jedynie przekształcić na lepszy.

1

Zrealizowanie kopiowania przez operator przypisania to nie jest najlepsze rozwiązanie, bo nie wiadomo jak to kopiowanie zostało zrealizowane. W przypadku operatora przypisania z C# bez wątpliwości można stwierdzić jaki będzie wynik tej operacji. Microsoft zaleca zrobić metodę explicit do tego, odpowiednio udokumentowaną. I nie korzystanie z przestarzałego interfejsu ICloneable, bo pozostaje ten sam problem co wcześniej.

1

Ogólnie C++ i C# to są dwa zupełnie różne języki. To, że niektóre słowa kluczowe, czy operatory są takie same to nie znaczy, że zachowują się tak samo. No i w sumie bardzo często zachowują się inaczej.

W tym wypadku porównywanie operatorów przypisania nie ma najmniejszego sensu. Przecież klasy w C# są typami referencyjnymi w przeciwieństwie do C++. Jak w C++ zrobisz tak:

Foo *wsk1 = new Foo;
Foo *wsk2;
wsk2 = wsk1;

i narzekał, że oba wskaźniki pokazują na te same, zamiast na różne obiekty.
Dodając do tego brak operatora dereferencji(wyłuskania) w C# to powinieneś już załapać, że "ulepszanie" operatora= nie ma po prostu najmniejszego sensu.

0

W c# tez mozna do takiej sytlacji doprowadzic.

Osoba a = new Osoba();
Osoba b = new Osoba();
a = b;

W tym wypadu a pokazuje na to samo co b, nie kopiując obiektu. I tu własnie można by zastosować operator= który by załatwił sprawę.

1

„Przychodzisz” do C# z C++, zrozumiałe jest że szukasz tych samych konstrukcji na zasadzie „jak to będzie w C#”.
Ja „przyszedłem” do C# z Delphi, i naturalne dla mnie było że operator przypisania dokonuje przypisania, koniec kropka, basta.
Do niektórych rzeczy po prostu trzeba się przyzwyczaić.

W C# operator przypisania dla typu referencyjnego (class) powoduje przypisanie referencji. Dla typu wartościowego (struct) powoduje utworzenie płytkiej kopii.
W obu przypadkach język nie daje możliwości wpłynięcia na zachowanie operatora.

0

Dzisiaj się na wykładzie dowiedziałem ze operatora= nie da się przeładować :/ Zostaje tylko konstruktor kopiujący.

0
Bumcykowy napisał(a)

Dzisiaj się na wykładzie dowiedziałem ze operatora= nie da się przeładować :/ Zostaje tylko konstruktor kopiujący.

Nie da, bo nie ma takiej potrzeby. Operator = powoduje przypisanie obiektu do zmiennej i tylko to.
Jeśli chcemy utworzyć głęboką kopię jakiegoś obiektu, to musimy napisać sobie metodę kopiującą jego pola i jawnie tę metodę wywołać. Dzięki temu kod jest czytelny, na pierwszy rzut oka wiadomo o co chodzi, i jakie były intencje autora.

Student s = new Student("Antoni", "Kowalski", "1234");
Student t = s; // ten sam obiekt w pamięci, zmiana wartości pól/właściwości w jednym spowoduje zmianę w drugim
Student u = s.Sklonuj(); // inny obiekt w pamięci, ich pola i właściwości można zmieniać oddzielnie

Prościej się tego nie da zrobić.

Można za to przeładować operator konwersji, dzięki czemu można dokonać niejawnej konwersji, która wygląda jak przypisanie obiektu jednego typu do zmiennej innego typu: http://msdn.microsoft.com/en-us/library/85w54y0a.aspx

1

Zostaje tylko konstruktor kopiujący.
Ja myślę że twój „problem” wynika z tego, że kompulsywnie chcesz coś kopiować.
W C# potrzeba skopiowania obiektu (i to na dodatek w jakiś „własny” sposób, skoro chcesz przeładować operator) jest znacznie rzadsza niż w C++.

Obiekt skopiowany oznacza że w pamięci trzymamy dwa razy to samo — a patrz zasada DRY.

0

Obiekt który kopiuje się przy użyciu = to struktura(słowo kluczowe struct).
Możesz też zrobić ten sam trik co string - niezmienna (immutable) klasa i przeładowany ==.

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