Eine Frage zu Scopes in C#



  • Zunächst: Ich komme eigentlich von C/ C++ und daher sind mir nicht unbedingt alle Konzepte von C# gleichermassen vertraut. Zum Beispiel finde ich es nach wie vor irritierend, dass es keine Includes gibt, was dann auch zu dieser Frage hier führt.

    Ich schreibe eine Windows Anwendung, daher wird vom VS die Datei "Form1.cs" bekanntlich automatisch erzeugt. Füge ich einem Steuerelement dieses Formulars per Doppelklick neue Funktionen hinzu, werden sie in dieser Datei gecoded.

    Wenn ich jetzt in dieser Datei z.B. ein DataSet ansprechen will (welches ich über den Datenquellenassistenten hinzugefügt habe), kann ich das in der "Form.cs" Datei benutzen, alle Member dieses DataSet sind bekannt, der ConnectionString kann verwandt werrden, ohne ihn neu schreiben zu müssen...alles Prima.

    Wenn ich nun der Übersicht halber Funktionalitäten in andere Klassen auslagern will (Hinzufügen-> Neue Klasse) wird dem Projekt eine neue *.cs Datei hinzugefügt, Member dieser Klasse sind vom Gleichen Namespace wie "Form1.cs" und in der Regel ist dies der Projektname.

    Ich kann so auch die Objekte anderer, dem Projekt( -namespace) zugehöriger Klassen nutzen, Ihre Member etc.

    Will ich hingegen in einer solchen *.cs File Das Dataset nutzen, so steht es mir nur eingschränkt zur Verfügung, nicht alle Memeber sind bekannt, mein Connection String ebenfalls nicht...in der Form1.cs Klasse sind sie es hingegen schon. Warum? Und wie gebe ich dies auch den anderen Klassen bekannt? Includes gibt es nicht, "friend" auch nicht...?



  • Das hat mit includes und Dateien erstmal gar nichts zu tun, sondern nur mit Sichtbarkeit. Du musst dir eigentlich nur mal den Code ansehen, den der GUI-Designer generiert. Der sieht dann so aus:

    class Form1 {
        [...]
        private Button myButton;
        private DataSet myDataSet;
        [...]
    }
    

    Und jetzt ist auch völlig klar, warum das DataSet nur innerhalb der Klasse Form1 zur Verfügung steht. 😉



  • Eben nicht. die Methoden fuer die Buttons etc. sind private. Das DataSet ist nichteinmal in dieser Klasse deklariert.



  • ja wie Optimizer schon sagte einfach mal den generierten Code in bequemer zurückgelehnter Haltung angugcken.

    Harte lösung für Klassenmember:
    -------------------------------
    Zur Not dann von den Membern die man woanders braucht private ---> zu public
    ändern. Ich weiss die gefällt nicht wgen Geheinisprinzipverstoss, aber was solls zum "schnellen Testen"!

    Bessere Lösungen hinzufügen von Neuen oder vorhanden Elmenten:

    Ausgangspunkt ein Formular was in anderen Instanzen/Klassen/Objekten nutzbar sein soll!
    Spendier Deinem Hauptformular eine Selbstgebastelte-Property.
    Das können die zusätzlichen Klassen dann nutzen indem Du diesen über Ihren Konstruktor eine Instanz Deines HauptFormular gibst.

    // Beispiel eines Hauptformular wild aus meine Wust aus Projekten genommen
    namespace OpwWirtschaft
    {
       public class Form1 : System.Windows.Forms.Form
       {
         private DataSet ds = null; // Das brauche ich auch woanders
    
         public DataSet Datenquelle
         {
             get
             {
                 return ds;
             }
         }
    
      } 
    }
    

    1. Bei Neuen Elementen ist das so:
    ----------------------------------
    So wenn Du jetzt in der IDE z.B über den Projektexplorer
    ein neues Element hinzufügst wird eine Datei generiert Endung .cs
    diese bekommt durch den Codegenerator gleich denselben Namensraum wie dein
    Hauptprojekt in dem Fall OpwWirtschaft
    Dort in der Datei hast Du dann Deine Klasse dort änderst Du dann den automatisch gecodet Konstruktor ab oder machst eine zweiten rein Der als Übergabeparameter
    Dein Hauptformular bekommt. Ist soweit in C++ auch nicht weiter wild und sollteeinem gleich bekannt vorkommen.

    hinzugefügte wird dadurch .cs-File, mit Namensraum der Hauptquellcodedatei deines Projektes, wie Du selbst ja auch schon festgestellt hast!
    zumeist sieht man im Projektexplorer dann eine neue Datei mit dem Namen Class1.cs

    namespace OpwWirtschaft
    {
       public Class1
       {
         // Konstruktur vom Codegenerator den Du con seiner Signatur abändern kannst
         public Class1()
         {
    
         }
    
         private DataSet ichwillDasDataSetAusForm1;
         public Class1(Form1 form1)
         {
            ichwillDasDataSetAusForm1 = form1.Datenquelle;
         }
    
      } 
    }
    

    2.Oder man fügt schon bestehende Objekte/Resourcen auch Assembly genannt ins Projekt ein:
    ---------------------------------------------------------------------------
    über den Projektexplorer --> Kontextmenü ---> "Verweis hinzufügen"
    hast Du bestimmt schon gesehen

    Durch diesen Vorgang bekommst Du im Objektexplorer den eigeladen
    Namensraum mit seinem Inhalt angezeigt. Kannst es ohne ein using gemacht zu haben im Code aber noch nicht nutzen.

    Um vorhanden Komponeten,Bibliotheken etc zu nutzen also so vorgehen
    1. über den Projektexplorer --> Kontextmenü ---> "Verweis hinzufügen"
    2. Komponete zugänglich machen in dem ein using auf den Namensraum
    der hinzugefügten Resource/Assembly gemacht wird

    D.h in einem anderen Projekt würde ich ein Verweis aufnehmen
    Wenn dürftige Doku zu diesem Assembly vorhanden ist gucke ich in den
    "Objektexplorer" der IDE, weil dann kenne ich den Namen der Namensräume.
    Das ermöglicht mir dann in meinem Projekt am Anfang ein using zu machen
    um es wirklich auch nutzen zu können.

    using Namensraum.Den.ich.über.DenObjektexplorerInErfahrungBringen.Konnte.über.die.externe.Resource;
    

    In jeder Klasse des Projektes wo ich die eingebundene Resource nutzen will muss
    ein entsprechendes using auf den Namensraum die diese Resource mitbringt existieren.

    hmm ich hoffe ich konnte mich mit Händen und Füssen irgenwie gut ausdrücken



  • muss mich korrigieren

    nicht Objektexplorer sondern heisst Objektbrowser



  • Guckmal nach wenn Du dei Datenbankverbindung per Assitent gemacht hast und das DataSet über eine Datenbankadapter per rechtsklick auf diesen im Formulardesigner gemacht hast wird dieses DataSet an den Namensraum deines Projektes gebunden.

    mein Projektnamensraum heisst ja OpwWirtschaft

    deshalb wurde vom Quellcodegenerator bei mir das Ding so
    deklariert

    private OpwWirtschaft.DataSet1 dataSet11;
    

    bei Dir müsste
    es

    private SarumansNamensraum.DataSet1 dataSet11;
    

    heissen im Hauptformular deines Projektes.



  • Such in der Quellcodedatei Deines Hauptformular wieder
    per STRG+F und gib als Suchzeichenkette den Namen der Instanz
    des DataSet ein, die solltest Du ja kennen.

    Dann müsstes Du auch über die Deklaration stossen.

    Dann ein Property in die Klassendefinition rein
    vom Typ der Instanz Deines gefunden DataSet.

    // im Hauptformularklasse definierte Property
    public DataSet Datenquelle
    {
       get
       {
           return this.DataSetInstanzvariable;
       }
    }
    

    Willst Du nun in anderen Klassen dieses DataSet nutzen
    parametrisieren deren Konstruktur oder deren Methoden mit eine Variablen vom Typ
    Deiner Hauptformularinstanz.
    Dann kannst Du im Konstruktor oder den Methoden von der Parametervariablen
    die Eigenschaft/Property "Datenquelle" nutzen.



  • Alles was im Entwurfsmodus per Drag and Drop aus der Toolbox aufs Formular gezogen wird.

    Auch das was im Projektmappenexplorer hinzugefügt wurde

    müsste man im Objektbrowser der IDE wiederfinden!
    Im Tree-View des Objektbrowser dann einfach den Projektnamensraum der als
    Baumknoten sichtbar ist aufklappen.

    P.S.: Objektbrowser ist z.B. auch dann sehr nützlich wenn man Verweise
    auf alte COM- und ActiveX-Steuerelemente ins Projekt aufnimmt.



  • Objektbrowser
    Projektexploerer == Projektmappen-Exploerer

    Erreichbar indem du das Menü "Ansicht" obere Leiste aufklappst.



  • Danke für die ausführliche Antwort!! Hast echt geholfen.


Log in to reply