Entwickler-Ecke

C# - Die Sprache - Klasse erweitern


traceurmicha - Mo 21.10.13 13:44
Titel: Klasse erweitern
Hallo, ich habe eine Klasse Presence im Namespace Firmenname.Verwaltung.Anwendung, diese möchte ich erweitern, im Namespace Anwesenheit habe ich also noch eine Klasse Presence.

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
namespace Anwesenheit
{
    #region Klasse Presence
    
    public class Presence : Firmenname.Verwaltung.Anwendung.Presence
    {
        #region Öffentliche Konstruktoren

        /// <summary>
        /// Initialisiert ein leeres Presence Objekt
        /// </summary>
        public Presence()
            :base()
        {
            
        }
        public bool Save()
        {
            //hier ist die Speicherlogik drin
        }
    }
}


Wenn ich jetzt in einem Webservice der ebenfalls im namespace Anwesenheit liegt ein Objekt Presence erzeuge und Save aufrufen will geht das nicht mit der Fehlermeldung


Quelltext
1:
enthält keine Definition für "Save", und es konnte keine Erweiterungsmethode "Save" gefunden werden, die ein erstes Argument vom Typ "Firmenname.Verwaltung.Anwendung.Presence" akzeptiert. (Fehlt eine Using-Direktive oder ein Assemblyverweis?)                    


Nun ist die Frage warum? Und wie kann ich die Methoden erweitern?


Ralf Jansen - Mo 21.10.13 14:39

Zitat:
Nun ist die Frage warum? Und wie kann ich die Methoden erweitern?


Du meinst du willst eine vorhandene Klasse um eine weitere Methode erweitern oder du willst eine vorhandene Methode um Funktionalität erweitern?

a.) wenn du keine interna von Anwendung.Presence brauchst (Dinge die als internal oder protected markiert sind) dann schreib eine Extension Method [http://msdn.microsoft.com/en-us/library/vstudio/bb383977.aspx] anstatt eine neue Klasse abzuleiten.
b.) du überschreibst [http://msdn.microsoft.com/en-us/library/ebca9ah3.aspx] die Save Methode aus Anwendung.Presence. Dafür muß die aber auch in Anwendung.Presence vorhanden sein.
c.) du programmierst an der entsprechenden Codestelle auch gegen Anwesenheit.Presence und nicht gegen Anwendung.Presence denn nur die hat im Moment scheinbar die Save Methode.
d.) siehe bei @TH69 (das offensichtliche glatt übersehen)


Th69 - Mo 21.10.13 14:41

Hallo,

Klassen können in C# nur mit dem Schlüsselwort partial erweitert werden oder aber alternativ in einer statischen Klasse eine Erweiterungsmethode schreiben (die als ersten Parameter this Klassenname hat.

So wie du es jetzt geschrieben hast, erstellt du eine neue Klasse im Namensbereich Anwesenheit, welche von der gleichnamigen Basisklasse (aber aus dem anderen Namensbereich) erbt.


Palladin007 - Mo 21.10.13 15:43

Schaut euch doch mal die Fehlermeldung an ^^


Er übergibt der Methode einen Parameter vom Typ "Firmenname.Verwaltung.Anwendung.Presence" und es ist keine Methode von diesem Typ da.


Wozu brauchst du denn überhaupt den Parameter? Reicht nicht die eigene Instanz zum Speichern aus? Und die hast du, da du ja von diesem Typ erbst. Bei Erweiterungsmethoden hättest du die Instanz auch.

Wenn du also die Presence speichern möchtest, die das aktuelle Object darstellt, dann würde ich den Parameter weg lassen und in der Methode Save this benutzen.




Allerdings, wie die Anderen schon geschrieben haben, bietet sich hier eine Erweiterungemethode an, wenn du keine internen Dinge der Klasse benötigst:


C#-Quelltext
1:
2:
3:
4:
public static void Save( this Firmenname.Verwaltung.Anwendung.Presence source)
{
    // Speicher-Logikt mit source
}


Ralf Jansen - Mo 21.10.13 15:51

Zitat:
Er übergibt der Methode einen Parameter vom Typ "Firmenname.Verwaltung.Anwendung.Presence" und es ist keine Methode von diesem Typ da.


Nein. Er ruft einfach Save() auf. Nur halt an einer Klasse die das nicht hat. (Und wenn wir jetzt die BestPractices Designtheorie auspacken vermutlich auch nicht haben sollte ;) )


Palladin007 - Mo 21.10.13 21:42

Ich dachte VS wirft diese Fehler-Meldung, wenn die Methode da ist, aber die Parameter nicht passen.


Naja, wie auch immer, (an traceurmicha) dann instanziirt du wahrscheinlich einfach über die Basis-Klasse und nicht über die erbende Klasse.

Das hier:

C#-Quelltext
1:
var presence = new Firmenname.Verwaltung.Anwendung.Presence();                    

ist nämlich etwas Anderes, als das:

C#-Quelltext
1:
var presence = new Anwesenheit.Presence();                    


Das Zweite ist das, was du suchst, denn die hat auch die Methode Save().

Vielleicht wäre hier auch ein anderer Name angebracht, damit du nicht immer an die Namespaces vor der Klasse angewiesen bist. Das kann man machen, aber ich finde, wenn es sich vermeiden lässt, dann lieber vermeiden.



Zu dem was Ralf sagt (immer noch an traceurmicha):

Ralf hat vollkommen Recht mit dem, was er in Klammern schreibt.
Es gibt so eine Regel, die besagt, dass jede Klasse immer nur eine Aufgabe haben darf. (Nachzulesen unter Single-Responsibility-Prinzip [http://de.wikipedia.org/wiki/Single-Responsibility-Prinzip])
Wenn du dann noch eindeutige und gut verständliche Namen vergibst, dann wird dir das bei größeren Projekten viel Zeit und Nerven ersparen.

Daten-Speicherung und Daten-Bereitstellung ist dabei ein Unterschied (je nach Umfang des Projektes, ein sehr Großer), das sind zwei verschiedene Aufgaben.
Da solltest du daher eine weitere Klasse speichern, die dazu zuständig ist, deine Presence-Objekte zu speichern.

Es ist auch nicht schlimm, wenn eine Klasse sehr kurz wird, solange sie ihre Aufgabe sinnvoll erfüllen kann.