Du bist nicht angemeldet.

Werbeanzeige

1

05.06.2020, 16:22

c# - Weg zum löschen, sortieren und entfernen von Elementen erlaubt aber nicht gezieltes Ändern der Listwerte?

Hallo Leute,

ich habe eine allgemeine Frage was Datenstrukturen angeht und zwar:

Gibt es eine Datenstruktur in .NET/C# mit der ich: (Löschen, Hinzufügen und Sortieren) kann ABER NICHT will, das man die einzelnen Werte selber verändern kann, also ich will das hier verhindern!:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
var data =  GetAFullArrayFromSomewhere(somedatabase)
data[0] = 10; //compiler error erwünscht!
data[1] = 11;
...etc...

//ODER.
var data = GetAFullListFromSomewhere(somedatabase)
data[0] = 10; //compiler error erwünscht!
data[1] = 11;//compiler error erwünscht!

data.Add(12); //OK!
data.Remove(10) //OK!

usw.


Der Sinn dahinter ist einfach, dass ich eben wie im Beispiel eine Liste fancy mäßig berechnen lasse sie daraufbasierend aufbaue, in einer abstrakten Klasse ABER NICHT will das die vererbenden Klassen diese Listenwerte manipulieren, die sollen die einfach nehmen und bei belieben (Löschen, Hinzufügen und Sortieren) aber halt nicht die Werte ändern!

Würde mich sehr freuen von Euch zu hören!

Beste Grüße

MonkaBoy

Wirago

Alter Hase

Beiträge: 1 212

Wohnort: Stockerau

Beruf: CRM Application Manager

  • Private Nachricht senden

2

05.06.2020, 21:15

Ich fürchte du wirst nicht drum rum kommen eine eigene Klasse dafür zu bauen. Add/Sort/Delete-Methoden entsprechend verfügbar machen.

3

06.06.2020, 03:46

Hi Wirago,

ja denke ich auch, naja kein thema, ist ja nur ein kleiner Wrapper, dachte halt nur .NET(Ti) bietet da etwas (.net)tes an :--D

trotzdem danke dir !

LInsoDeTeh

Treue Seele

Beiträge: 373

Wohnort: Essen, Deutschland

Beruf: Team Lead Inhouse-Entwicklung

  • Private Nachricht senden

4

06.06.2020, 09:45

Es gibt in .NET die ReadOnly-Collections. Damit werden Manipulationen an der Collection verhindert, auch durch Zugriff über einen Index. Diese sind praktischerweise von allen möglichen anderen Collections (z.B. List<T>) implizit castbar. Du bräuchtest dann nur die Add und Delete Methoden zur Verfügung zu stellen. In etwa so (hab's nicht im Editor auf Syntax geprüft):

C#-Quelltext

1
2
3
4
5
6
7
8
abstract class BaseClass {
  private List<int> myCollection;
  
  protected ReadOnlyCollection<int> MyCollection { get { return myCollection; } }
  protected void Add(int value) { myCollection.Add(value); }
  protected void Delete(int index) { myCollection.RemoveAt(index); }

}


Eine abgeleitete Klasse davon hat dann keinen Zugriff auf die schreibbare myCollection, sondern nur auf die schreibgeschützte MyCollection und die explizit von dir bereitgestellten Add/Delete-Methoden.

Hinweis: Wenn du Objekte statt int-Werte in deiner Liste aufbewahren willst, kannst du auf diese Weise aber nicht verhindern, dass jemand nach Zugriff auf MyCollection die Eigenschaften der Objekte ändert, nur die Collection selbst ist dadurch geschützt. In dem Fall musst du die Zugriffe zusätzlich an der Objektklasse selbst regeln (z.B. mit Properties, die nur Getter haben).

5

07.06.2020, 00:13

Ich danke dir ebenso für die Antwort, @LinsoDeTech

ja das werde ich auch so ziemlich machen, sehr guter Einfall :-)

6

09.07.2020, 08:04

Reintheoretisch angefragt, aber könnte man auch komplett den {set;} Zugriff auf Listenelemente verhindern?

C#-Quelltext

1
2
3
4
5
6
7
8
9
var myObject = new MyObject(...);
myObject.MyPropertyString = "new value for me1"; ---------> //Allowed!



var myReadonlyList = new ReadOnlyList<MyObject>(...);
myReadonlyList.Add(myObject);
myReadonlyList[i].MyPropertyString = "new value for me2"; ---------> //Forbidden!
var whatsInThere = myReadonlyList[i].MyPropertyString; // -----------> //Allowed


Aber, ohne das ich den get/set accessor in der Klasse anpassen muss, sondern das quasi NUR innerhalb dieser ReadOnlyList sorte, es NUR lesende Zugriffe geben kann, sowohl für das Ganze Objekt als auch für seine Felder, falls <T> sich um eine nicht primitive Datenstruktur handelt natürlich, aka Klasse/Struct.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »MonkaBoy« (09.07.2020, 08:18)


David Scherfgen

Administrator

Beiträge: 10 311

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

7

09.07.2020, 09:31

Nein, das geht allgemein nicht. Denn das, was du verbieten möchtest, ist aus Sicht der Liste ein lesender Zugriff. Du fragst die Liste nach dem Element an Stelle i, und sie gibt es dir. Das ist Lesen (Schreiben wäre: Setze ein Element an Stelle i). Was du danach mit dem Element machst (nämlich es verändern), weiß die Liste nicht und kann sie auch nicht wissen. In C++ geht das mit const, in C# gibt's das aber nicht.

Mit structs als Elementen könnte es jedoch gehen, weil die Liste dann nur Kopien rausgibt, und wenn du die änderst, bleibt das Original in der Liste unverändert. Habe ich nicht ausprobiert, müsste aber so sein. Structs sind aber in C# mit Vorsicht zu genießen.

LInsoDeTeh

Treue Seele

Beiträge: 373

Wohnort: Essen, Deutschland

Beruf: Team Lead Inhouse-Entwicklung

  • Private Nachricht senden

8

09.07.2020, 17:36

Was du natürlich machen könntest, wäre mit einer Art ViewModel zu arbeiten. Dann müsstest du die Liste mit ihren Inhalten allerdings jedes Mal neu erzeugen, wenn sie angefragt wird. So in etwa:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class OriginalModel {
  public string Property1 { get; set; }
  public int Property2 { get; set; }
}

class ViewModel {
  public string Property1 { get; private set; }
  public int Property2 { get; private set; }

  public ViewModel (OriginalModel model) {
    this.Property1 = model.Property1;
    this.Property2 = model.Property2;
  }
}

class MyList {
  private List<OriginalModel> originalList;

  public ReadOnlyCollection<ViewModel> GetList() {
    return this.originalList.Select(om => new ViewModel(om));
  }
}


Wenn es dir wirklich wichtig ist, dass auch die Eigenschaften nicht geschrieben werden, kann man das bei kleineren Listen so machen. Für große Datenmengen in der Liste ist das .Select() bei jedem Aufruf natürlich teuer.

9

14.07.2020, 09:48

Vielen Dank für Eure Hinweise und Ratschläge!

Ich glaube ich probiere es mit deiner Lösung, @Linso

Hört sich plausibel an :-)

Werbeanzeige