Implementacja listy c# a c++

0

Witam, chciałem spytać jaka jest właściwie różnica w implementacji listy w c#. Pisząc takie coś w c++ zawsze używałem wskaźników i jest to dla mnie całkowicie naturalne i zrozumiałe.

class element 
{
element *next; //wskaźnik
int wartosc;

element(int war)
{
wartosc = war;
next=NULL;
}
}
 

Natomiast w c# znalazłem takie coś


class Element
{
    public int wartosc;
    public Element next; // JAK TO rozumieć ?? 
    public Element(int w)
    {
        wartosc = w;
        next = null;
    }
}
 

I tu moje pytanie jak dokładnie rozumieć public Element next, to jest obiekt przechowujący kolejne elementy list czy jakoś inaczej należy to rozumieć? Pytam bo w c++ taki zapis był by nie legalny.

0

To nie jest obiekt tylko referencja do obiektu.

0

C# wszystko oprocz typow prostych przesyla jako referencje

0

Cała algorytmika takiej listy jest identyczna, ale implementowanie jest znacznie prostsze, bo masz GC i możesz po prostu nullować usuwane elementy albo je dispose'ować jeżeli będziesz chciał zaimplementować interfejs IDisposable dla elementów listy.

Tutaj masz przyklad takiej generycznej listy, którą napisałem. Można coś prawie identycznego zrobić za pomocą szablonów w C++.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LinkedList {
    class LinkedList<T> {
        public LinkedList() {
            this.head = null;
        }

        public void Add(T obiekt) {
            Element newElement = new Element(obiekt);
            if (this.head == null) {
                this.head = newElement;
                this.head.next = this.head;
                this.head.prev = this.head;
                this.head.last = this.head;
            }
            else {
                this.head.last.next = newElement;
                newElement.prev = this.head.last;
                this.head.last = newElement;
                newElement.next = this.head;
                this.head.prev = newElement;
            }
        }

        public void Print() {
            Element temp = this.head;
            do {
                Console.WriteLine(temp.obj.ToString());
                temp = temp.next;
            } while (temp != this.head);
        }

        /// <summary>
        /// Przy usuwaniu po prostu ustawiamy usuwaną referencję na null.
        /// GC zajmie się resztą. Ewentualnie można zaimplementować interfejs IDisposable
        /// dla klasy Element i wywoływać ręcznie metodę dispose.
        /// </summary>
        public void Remove(T obiekt) {
            Element temp = this.head;
            Element forDel = null;

            do {
                if (temp.obj.Equals(obiekt)) {
                    forDel = temp;
                    temp.prev.next = temp.next;
                    temp.next.prev = temp.prev;
                    if (temp == this.head) this.head = temp.next;
                    forDel = null;
                    break;
                }
                else temp = temp.next;
                
            } while (temp != this.head);
        }

        private Element head;
        private class Element {
            public Element(T obiekt) {
                this.obj = obiekt;
                this.next = null;
                this.prev = null;
                this.last = null;
            }

            public T obj { get; set; }
            public Element next { get; set; }
            public Element prev { get; set; }
            public Element last { get; set; }
        }
    }

    class Program {
        static void Main(string[] args) {
            LinkedList<string> lista = new LinkedList<string>();
            lista.Add("Grzegorz");
            lista.Add("Tomasz");
            lista.Add("Zbyszek");
            lista.Add("Marcin");
            lista.Remove("Marcin");
            lista.Print();
            Console.ReadKey();
        }
    }
}

https://ideone.com/LR8yBY

[EDIT]: Plus to o czym wspomnieli koledzy. Klasa jest typem referencyjnym więc

Element nastepny;

to tak naprawdę referencja/wskaźnik do obiektu na stercie.

0
fasadin napisał(a):

C# wszystko oprocz typow prostych przesyla jako referencje

W C# nie ma typów prostych, ściślej - nie ma oficjalnej definicji takiego typu. Raz jest mowa o tym, że są to wszystkie typy z namespace System, innym razem tylko te wartościowe. Najlepsze rozwiązanie, to nie używać tego słowa w tym kontekście, skoro nawet Microsoft się nie może zdecydować.
I tak jak napisałem w komentarzu - co to jest "wszystko"? Bo wszystkiego na pewno nie. tak nie przesyła.

grzesiek51114 napisał(a):

Cała algorytmika takiej listy jest identyczna

Cała nauka o algorytmach takiej listy jest identyczna...
Niemniej jednak nie uważam marchewka wstawiania losowych słów w ogórek losowych miejscach pomidor za dobre.

bo masz GC i możesz po prostu nullować usuwane elementy albo je dispose'ować jeżeli będziesz chciał zaimplementować interfejs IDisposable dla elementów listy.

Jakie jest możliwe i prawdopodobne praktyczne zastosowanie IDisposable dla elementu listy? Najchętniej zobaczyłbym implementację czegoś takiego.

[EDIT]: Plus to o czym wspomnieli koledzy. Klasa jest typem referencyjnym więc

Element nastepny;

to tak naprawdę referencja/wskaźnik do obiektu na stercie.

Referencja tak, wskaźnik nie. Referencje i wskaźniki to coś zupełnie innego.

Przy czym użycie tutaj słowa więc nie ma sensu. Miejsce przechowywania obiektu nie ma nic wspólnego z tym, jaki jest jego typ. To tylko szczegół implementacji.

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