Autor |
Beitrag |
Adabei
      
Beiträge: 33
|
Verfasst: Di 19.08.14 16:45
Hallo liebe Community!!!
Zuerst einmal, ich bin ein C#-Anfänger und kennen mich leider nicht so gut aus, also wenn etwas unklar ist, wenn ich was beschreibe einfach nachfragen
ich habe eine Liste mit einer Anleitung von meinem C#-Buch erstellt, diese Liste will ich nun in eine andere Klasse schicken, leider funktioniert das aber nicht gleich wie bei normalen Variablen.
meine liste heißt: lists, die erste Klasse heißt Form1, die zweite Form2 ;
Ich habe die Liste in Form1 erstellt und will sie nun in Form2 schicken, mit Methoden habe ich dass probiert(geht ja auch mit eigenschaften, soviel ich weiß, habe dieses Kapitel aber nur durchgelesen und nicht ausprobiert, da es ja eh auch mit Mehtoden geht)
C#-Quelltext 1: 2: 3: 4: 5: 6: 7:
| Form2 f = new Form2(); f.alles = lists;
if (f.ShowDialog() == DialogResult.OK) {
} |
ich habe in Form 2 erstellt
C#-Quelltext 1: 2: 3:
| public string alles { } |
und jetzt will ich die Liste: lists dort rüber schicken, denn so wie ich es gemacht habe funktioniert es nicht, wenn ihr die Fehlermeldungen braucht(2 sind es), dann kann ich sie eh schicken, aber ich glaube ich habe was grundlegende falsch gemacht, denn wsl. geht listen schicken nicht gleich wie variablen schicken.leider wird im Buch nur das schicken von Variablen erklärt
lg
adabei
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Di 19.08.14 17:31
Alles sollte eine Property sein.
C#-Quelltext 1: 2: 3: 4: 5: 6:
| private string alles public string Alles { get { return _alles; } set { _alles = value; } } |
C#-Quelltext 1: 2:
| Form2 f = new Form2(); f.Alles = lists; |
Du solltest aber noch mal über den Typ von Alles nachdenken. Du sprichst von List willst aber als Typ aber string verwenden. Die Typen müssen schon zueinander passen.
Für diesen Beitrag haben gedankt: Adabei
|
|
Palladin007
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Di 19.08.14 18:01
Es geht durchaus, wenn du eine Variable in einer Klasse als public (oder internal) kennzeichnest und dann einfach über das Objekt der Klasse die Variable erreichst.
Da kannst du dann genauso schreiben, wie bei anderen Variablen auch.
C#-Quelltext 1: 2: 3: 4:
| public class Person { public string Name; } |
Nutzung:
C#-Quelltext 1: 2:
| var person = new Person(); person.Name = "Hans Vader"; |
Es geht zwar, gilt aber als unsauber, weshalb das nicht gerne gesehen ist.
Stattdessen gibt es die Properties (deutsch: Eigenschaften). Sie lassen sich auf die selbe Weise nutzen, sehen aber anders aus:
C#-Quelltext 1: 2: 3: 4:
| public class Person { public string Name { get; set; } } |
oder
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| public class Person { private string _name; public string Name { get { return _name; } set { _name = value; } } } |
Die erste Variante ist eine Kurzform, die der Compiler dann in die zweite Variante auf dröselt.
Das hat einen großen Vorteil: Du kannst das Verhalten beim Schreiben/Lesen beeinflussen.
In dem get-Block passiert das lesen (es wird die Variable _name zurück gegeben) und im set-Block das Schreiben. Beim Schreiben repräsentiert value den Wert, der in die Eigenschaft geschrieben werden soll, daher wird hier dieser Wert in die Variable _name geschrieben.
Nun kannst du entweder die Zugriffsberechtigung auf das Schreiben/Lesen ändern, indem du einen Zugriffsmodifizierer ( public, private, protected, internal), oder du kannst das Verhalten selber ändern.
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| public class Person { private string _name; public string Name { get { return _name; } private set { if (string.IsNullOrEmpty(value)) throw new ArgumentNullException();
_name = value; } } } |
Hier kann der Name nur privat in der Klasse geändert werden und wenn der gesetzte Wert null oder leer ist oder nur aus Leerzeichen besteht, dann wird eine Exception (Ausnahme) ausgelöst, die im schlimmsten Fall das Programm abbrubt beendet. Diese Exceptions kennst du vielleicht von Programmen, die hart abstürzen und irgendwelche kryptisch wirkende Fehlermeldungen bringen. Das dürfte dann sehr wahrscheinlich so eine Exception gewesen sein.
So hast du jetzt in diesem Beispiel erreicht (wenn du z.B. eine Datenbank hast und der Name immer vorhanden sein muss), dass ein falscher Schreib-Versuch direkt abgefangen wird und nicht erst die Datenbank einen noch verrückteren Fehler wirft. Außerdem kannst du dort dann selber entscheiden, wie du mit dem falschen Wert umgehst, du kannst z.B. auch eine Information mit einer gut lesbaren Fehlermeldung dem User anzeigen und daraufhin nicht in die Datenbank schreiben.
Oder du hast Variablen oder Eigenschaften, die von einem anderen Wert abhängig sind. Wenn sich dieser andere Wert nun ändert, dannst du in dem set-Block dafür sorgen, dass alle anderen abhängigen Werte angepasst werden.
DU kannst natürlich auch das Lesen im get-Block nach Außen verbieten und nur Schreiben erlauben. Das Funktioniert, aber sich jemals einen sinnvollen Anwendungsfall dafür findet, bezweifle ich.
Für die neue Version von C# baut Microsoft auch noch ein paar coole neue Features für die Properties ein, ich freue mich schon drauf. ^^
Dennoch muss (wie Ralf schon schrieb) der Typ überein stimmen, den du schreibst.
Außerdem (je früher desto besser) solltest du dir eine verständliche Namensgebung ausdenken.
Jede Firma hat da eine eigene Herangehensweise, aber eines ist immer gleich: Wenn ein Entwickler den Namen ließt, weiß er was in der Variable gespeichert wird.
Ich kann mir z.B. nichts unter "Alles" vorstellen und "Lists" ist genauso nichts sagend.
Für diesen Beitrag haben gedankt: Adabei
|
|
Adabei 
      
Beiträge: 33
|
Verfasst: Di 19.08.14 19:18
danke euch 2 für die Antworten
erstmals zur namensgebung: natürlich bei größeren Projekten sehr wichtig, aber da ich es nur zu Übungszwecken mache ist es glaube ich nicht so wichtig, aber wenn ihr es sagt, habe ich es gleich versucht in diesem Projekt umzusetzten, dass ihr euch eventuell besser was vorstellen könnt, leider habe ich die Klassen vergessen zum umbennennen, ich hoffe es ist nicht zu wichtig, bitte um verzeihung
ok, also ich habe jetzt einmal dass gleiche mit Eigenschaften programmiert, jetzt sieht es so aus.
in Form1:
C#-Quelltext 1: 2: 3: 4: 5: 6:
| Form2 f = new Form2(); f.PW = lists; if (f.ShowDialog() == DialogResult.OK) {
} |
in Form2:
C#-Quelltext
dass habe ich mal als globale variable errrichtet, dass ich bei set daten hinzufügen kann und bei get dann genauer noch bearbeitn;
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| public string PW { get { return c; } set { c=value.ToString() } } |
return c; habe ich nur gemacht, dass er nicht immer die Fehlermeldung anzeigt;
Folgende Fehlermeldung kommt immer:
"Eine implizierte Konvertierung vom Typ "System.Collections.Generic.List<Pw.Liste>" in "string" ist nicht möglich"
Dass ist vermutlich, dass was ihr gesagt habt, also wegen den 2 verschiedenen Typen, aber wie kann ich das problem lösen?
|
|
Palladin007
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Di 19.08.14 20:01
C#-Quelltext
Das ToString() brauchst du nicht. String bleibt string.
value enthält genau das, was die Variable enthält, die du in die Property schreiben willst. Bei Objekten ist es die Referenz und bei Werten der gleiche Wert.
Dabei hat value aber immer den selben Typ wie die Property.
Zitat: | return c; habe ich nur gemacht, dass er nicht immer die Fehlermeldung anzeigt |
Ich wüsste nicht, was das für einen Unterschied macht.
Dennoch solltest du den get-Block nie weg lassen, denn sonst hat die Property praktisch keinen Sinn mehr. Sie eine Property oder eben Eigenschaft als das, was sie ist: Eine Eigenschaft.
Auch Menschen haben Eigenschaften. Ein Kind ist z.B. 1 Meter groß. Jetzt wächst es und ist 1,10 Meter groß. Irgendwo im Programm, das ein Mensch-Objekt braucht, würde dann also diese Eigenschaft einen neuen Wert bekommen. Klingt es denn logisch, dass das Kind zwar wachsen kann, aber niemand die Größe wissen darf?
Wenn nur etwas gesetzt werden soll, dann nutze dafür am besten Methoden.
Was die zwei Typen angeht:
Wie stellst du dir das denn vor, du möchtest eine Liste mit Passwörtern (oder was da drin ist) in ein Passwort schreiben?
Dass der Compiler dir sagt, dass List<T> nicht in string konvertiert werden kann ist kein Problem, das ist genau richtig so. Viel eher solltest du dir überlegen, was genau du vor hast und dann schauen, wo der Fehler liegt. Wenn du z.B. ein bestimmtes Passwort dort rein geschrieben haben möchtest, dann musst du das auch tun. Du suchst also das bestimmte Passwort raus und schreibst es in die Eigenschaft, aber wie soll die Property denn wissen, wie sie das gesuchte Passwort findet?
Oder du möchtest alle Passwörter in der Property haben, dann änderst du den Typ und benennst sie entsprechend um (Passwords).
Als letztes bleibt noch, dass du tatsächlich die Liste als String haben willst. Die ToString-Methode tut auch nur, was der Entwickler ihr sagt. Normalerweise schreibt sie den genauen Namen des Typs auf, also der Liste. Was du aber machen kannst, um alle Passwörter in das eine Passwort zu kriegen, ist dir überlegen, wie die da drin stehen sollen. Wenn sie durch ein Komma getrennt sein sollen, musst du das so implementieren. Ein Passwort nach dem Anderen in die Property schreiben und dazwischen immer ein Komma setzen.
Für diesen Beitrag haben gedankt: Adabei
|
|
Adabei 
      
Beiträge: 33
|
Verfasst: Di 19.08.14 20:29
wenn ich return c; in die get eigenschaft rein schreibe, dann kommt keine Fehlermeldung, dass diese Anweisung keine Daten zurückschickt.
dass toString hatte ich nur zur sicherheit
ja ich möchte alle Passwörter in der Property haben, die Daten der Liste erstellt der Benutzer zuerst selbst, also gibt er in eine listbox was ein z.B. Passwort 1(Eintrag nummer 1 der liste) Passwort2(eintrag nummer 2 der Liste) Passwort 3.....
all jene daten sind nun in der liste gespeichert(will nicht alle einzeln bearbeiten/schicken-->deshalb liste(und ich muss es sowiso lernen mit listen umzugehen  ))
ja aber zu welchem Typ soll ich was ändern?
|
|
Palladin007
      
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Di 19.08.14 20:45
Achso, ja, ist klar, schließlich ist der get-Block sowas wie eine Methode mit Rückgabewert.
Wenn get weg soll, muss der ganze get-Block weg, nicht nur Inhalt. Das Gleiche gilt auch für den set-Block, wobei eher häufig das set weg gelassen wird, damit ist die Property eben Readonly.
Überleg dir, wie die in der Property stehen sollen. Wenn sie als String drin stehen sollen, musst du dir überlegen, wie die String-Darstellung aussehen soll, wenn du sie als Liste drin haben willst, musst du den Typ der Property in eine Liste ändern.
Das habe ich aber alles schon geschrieben und es schadet auch nicht, einfach mal auszuprobieren.
Für diesen Beitrag haben gedankt: Adabei
|
|
Adabei 
      
Beiträge: 33
|
Verfasst: Di 19.08.14 21:57
ja genau, nein weglassen will ich eig. keine der beiden blöcke...
typ der Property ist ja eigentlich dann var oder?
also
C#-Quelltext 1: 2:
| var f=new Form2(); f.Passwords=lists; |
trotzdem nimmt es dann die liste nicht an und es zeigt die gleiche Fehlermeldung an 
|
|
jfheins
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Di 19.08.14 22:03
Adabei hat folgendes geschrieben : | typ der Property ist ja eigentlich dann var oder? |
var sit kein Typ. var ist lediglich ein Schlüsselwort das bedeutet "Der Typ sollte ja offensichtlich sein, das soll der Compiler bitte mal selber herausfinden."
Wenn der Compiler das nicht herausfinden kann, wird er dir das schon um die Ohren hauen. Und später, wenn du eine Variable anguckst (Codevervollständigung z.B.) wird auch immer der korrekte Typ angezeigt.
Zu deinem Problem: Du musst deine Property vom Typ "List<string>" deklarieren. Also eine Liste mit stings darin:
C#-Quelltext 1:
| public List<string> PW { get; set; } |
Für diesen Beitrag haben gedankt: Adabei
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Di 19.08.14 22:46
Zitat: | Zu deinem Problem: Du musst deine Property vom Typ "List<string>" deklarieren. Also eine Liste mit stings darin: |
Zitat: | "Eine implizierte Konvertierung vom Typ "System.Collections.Generic.List<Pw.Liste>" in "string" ist nicht möglich" |
Sicher? 
Für diesen Beitrag haben gedankt: Adabei
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mi 20.08.14 09:14
Hallo Adabei,
damit dieses Thema nicht endlos so weitergeht, poste bitte die Deklaration deiner Variablen lists, d.h. den genauen Datentyp davon (was ist Pw.Liste?).
Und genau diesen Datentyp mußt du dann auch als Typ der Eigenschaft Passwords angeben.
Für diesen Beitrag haben gedankt: Adabei
|
|
Adabei 
      
Beiträge: 33
|
Verfasst: Mi 20.08.14 09:50
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mi 20.08.14 10:17
Ich hoffe mal in dem Buch heißt die Klasse nicht Liste sondern es war deine (eher schlechte) Idee. Wenn doch gehört der Autor gevierteilt. Nenne die Klasse nach dem wofür sie gedacht ist, also zum Beispiel Credential und die beiden Properties Username bzw. Password.
Wie auch immer. Der Typ deiner Liste ist List<Liste>. Wenn du die Instanz dieser Klasse woanders auch brauchst dann sollte die Variable, Feld, Property, Parameter die den aufnimmt vom gleichen Typ sein (das ist erst mal genau genug für einen Anfänger, die dreckige Wahrheit kommt später). Beim reinen Rechnen würdest du ja auch nicht einfach die Einheiten ändern, z.B. von Euro nach Dollar ohne irgendwas zu tun. Also muß deine Property auch von diesem Typ List<Liste> sein nicht von string.
Für diesen Beitrag haben gedankt: Adabei
|
|
Adabei 
      
Beiträge: 33
|
Verfasst: Mi 20.08.14 11:33
ja war meine idee, wie gesagt, bin noch Anfänger
aso, ok, jetzt verstehe ich was ihr eigentlich die ganze Zeit mir zu sagen versucht habt, im nachhinein irgendwie verständlich, dass es nicht geht wenn man 2 verschiedene Paramtertypen verwendet.
Leider kommt dann eine neue Fehlermeldung:
Inkonsistenter Zugriff: Eigenschaftstyp <PW.Liste> weniger zugreifbar als Eigenschaft "Pw.Form2.Passwords"
Das Problem was nun besteht hat ja mit der Erreichbarkeit, also private oder public zu tun(habe ich nach google suche und hier in forumssuche herausgefunden)
allerdings kann ich die Klasse Liste nicht public machen, sonst kommen wieder neue(alte) Fehlermeldungen.
hier nochmals die Klasse die auf public aufgewertet gehört.
C#-Quelltext 1: 2: 3: 4: 5:
| class Liste { public string a { get; set; } public string b { get; set; } } |
wenn ich die Klasse auf public ändere:
C#-Quelltext 1: 2: 3: 4: 5:
| public class Liste { public string a { get; set; } public string b { get; set; } } |
ist zwar die 1 Fehlermeldung weg, dann kommen aber wieder die Fehlermeldungen mit dem Konvertieren:
1. Eine implizierte Konvertierung von Pw.Liste auf "string" geht nicht und
2. "string" in Pw.Liste ist nicht möglich
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mi 20.08.14 12:07
Deine Property in Form2 sieht jetzt etwa so aus oder steht da immer noch string anstatt List<Liste>?
C#-Quelltext 1:
| public List<Liste> Passwords { get; set; } |
Für diesen Beitrag haben gedankt: Adabei
|
|
Adabei 
      
Beiträge: 33
|
Verfasst: Mi 20.08.14 12:19
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mi 20.08.14 12:48
m_c ist immer noch ein string. Und denn versuchst du als List<Liste> zu veröffentlichen über die Property. m_c muß natürlich auch vom Typ List<Liste> sein.
Das m_lbDaten.Items.Add(m_c); ist irgendwie Unsinn.
Möchtest du erreichen das wenn du irgendwas an der Passwords Property änderst das das sofort in irgendeinem Ui Control (lbDaten ist ein Listbox?) auftaucht?
Für diesen Beitrag haben gedankt: Adabei
|
|
Adabei 
      
Beiträge: 33
|
Verfasst: Mi 20.08.14 13:05
ja dass ist vermutlich schwachsinn mit der lb;
aja, stimmt, sonst ist ja wieder das problem wie von dir dargestellt mit euro/bzw. dollar;
danke an alle die mir jetzt geholfen habe!!!!!!!!!!!!
dass Problem ist gelöst
|
|
|