Wskaźniki w C# po raz nty.

Odpowiedz Nowy wątek
2012-02-08 14:16

Rejestracja: 17 lat temu

Ostatnio: 20 godzin temu

0

Cześć, nie mogę zrozumieć tych netowych wymysłów.
Potrzebuję zrobić coś takiego:

Mam sobie dwa obiekty dwóch różnych klas. A i B.
W obiekcie A tworzę sobie obiekt, który używa obiektu z B:

A.myObj.stream = B.GetStream();

I wszystko byłoby piękne, gdyby nie to, że stream zwracany w metodzie GetStream jest w pewnym momencie niszczony, a potem tworzony z nowymi danymi. W związku z czym zmienia się jego adres i traci się referencja w A.myObj.stream.

Więc wpadłem na świetny pomysł! Posłużę się wskaźnikami. A odkąd właściwie wszystko jest wskaźnikiem, to robota będzie prosta.

//uproszczony kod

private MyStream streamToReturn = null; //próbowałem też ze static

public void myFunc()
{
  mainStream.dispose();
  mainStream = new MyStream(jakies_parametry)

  streamToReturn = mainStream;
}

public MyStream GetStream()
{
  return streamToReturn;
}

Spodziewałem się, że obiekt streamToReturn ZAWSZE będzie miał ten sam adres w pamięci, ponieważ nigdy nie jest niszczony. Jednak okazało się, że nie.

Więc wyrywam sobie włosy z głowy. Jak to można zrobić inaczej? Jakoś za pomocą Marshal? Tylko jak?

Pozostało 580 znaków

2012-02-08 16:16

Rejestracja: 8 lat temu

Ostatnio: 8 lat temu

0

Po 1: Nie wskaźniki tylko referencje.
Po 2: Zwracając referencje tak naprawdę zwracasz tylko jej wartość (nie wskaźnik na nią). czyli gdy potem dajesz streamToReturn = new Blablabla() to referencja streamToReturn wskazuje na nowy obiekt.

W twoim wypadku najprostszym rozwiązaniem jest:
a) Pobierać za każdym razem referencje od nowa.
b) Stworzyć klasę "pośrednika" w której będzie referencja. Obiekty klas A i B będą korzystały z tej klasy. Obiekt A będzie przypisywał jakąś wartość do referencji, która znajduje się w pośredniku, a klasa B referencje będzie pobierać z pośrednika.

Trochę trudniejszym rozwiązaniem (dla nieobeznanych ze wskaźnikami rodem z C/C++) byłoby wykorzystanie kodu unsafe i pobranie wskaźnika na referencje streamToReturn. Oczywiście trzeba by się potem do niej odpowiednio dobierać.


Mój blog ;)</a>

Pozostało 580 znaków

msm
2012-02-08 18:28
msm
Administrator

Rejestracja: 10 lat temu

Ostatnio: 1 miesiąc temu

0
class MyStreamedData
{
    public MyStream CurrentStream { get; set; }
}

MyStreamedData mainStream;

public void myFunc()
{
  mainStream.CurrentStream.Dispose();
  mainStream.CurrentStream = new MyStream(jakies_parametry)
}

I żadnych wskaźników.

Pozostało 580 znaków

2012-02-08 19:37

Rejestracja: 16 lat temu

Ostatnio: 1 dzień temu

0

prawdziwe wskaźniki (w sensie „unsafe”) się do tego nie nadają, bo garbage collector może podczas swojego przebiegu przesunąć obiekt w pamięci, i wskaźnik przestałby być aktualny.

Pozostało 580 znaków

2012-02-08 21:37

Rejestracja: 17 lat temu

Ostatnio: 20 godzin temu

0

Po kolei.
Wywołanie jest w takiej kolejności:

myFunc
GetStream
myFunc <- i to wywołanie mi pieprzy wszystko, ale musi być.

Wskaźnik by mi sprawę załatwił, bo w myFunction po utworzeniu obiektu, od razu przepisywałbym wskaźnik. A miejsce wskaźnika w pamięci jest stałe, prawda?

Przerabiając to na Delphi(bardziej pseudokod):

type
  PMyStream = ^TMyStream;

var
  myStreamPtr: PMyStream;

procedure myFunc();
begin
  FreeAndNil(mainStream);
  mainStream:=TMyStream.Create(parametry);

  myStreamPtr:[email protected];
end;

function GetMyStream(): TMyStream;
begin
  result:=TMyStream(myStreamPtr)^;
end;

(niekoniecznie się to skompiluje, ale wiadomo o co chodzi)

edytowany 2x, ostatnio: Juhas, 2012-02-08 21:38

Pozostało 580 znaków

Odpowiedz

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