C# Interface Methoden werden nicht angezeigt

mosquito87

Lieutenant
Registriert
Aug. 2006
Beiträge
980
Hallo zusammen,

hänge zurzeit an einem kleinen Problem mit Interfaces.
Evtl. ist es auch ein Verständnisproblem, da ich aus der Java-Ecke komme.

Ich definiere in einem Interface "ITest" eine "abstrakte" Methode:

Code:
int getId();

In einer anderen Klasse wird nun ein Objekt vom Typ "ITest" an die Methode übergeben (Übergabeparameter). Das Objekt heißt "test".
Warum funktioniert nun test.getId() nicht? Die Methode ist nicht bekannt. :-(
 
Code vom Interface (das "Super"interface (IEntity) ist leer):
Code:
public interface ISqlEntity : IEntity
    {
        int Id
        {
            get;
            set;
        }

        int getId();
    }

Code der Methode, wo das Interface übergeben wird:
Code:
public override int updateEntity(DatabaseConnection db, ISqlEntity entity)
        {
            entity.getId() <- geht nicht ...
        }
 
Und die genaue Fehlermeldung lautet? Symbol nicht gefunden? Oder handelt es sich nur um einen IntelliSense-Fehler in Visual Studio ?
 
Hi,

ich habe es mal kurz nachgestellt und bei mir (VS2010) funktioniert es (ich habe der Einfachheit halber mal IEntity weggelassen).
Sollte also kein grundsätzliches Problem sein.

Genaueres kann ich dir allerdings so nicht sagen...

Gibt der Compiler eine Fehlermeldung oder funktioniert die Code-Vervollständigung nicht?

Grüsse,

T.
 
Du hast nicht zufällig 2 Interfaces, die sich einen Namen teilen, aber in unterschiedlichen Namespaces liegen?
 
Strange.

Intellisense funktioniert nicht (damit kann ich ja noch leben), aber der Compiler meckert ebenfalls:

"Error 1 'ISqlEntity' does not contain a definition for 'getId' and no extension method 'getId' accepting a first argument of type 'ISqlEntity' could be found (are you missing a using directive or an assembly reference?) C:\Users\Michael\Documents\Visual Studio 2010\Projects\MvcRepository\MvcRepository\Repositories\SqlRepository.cs 83 62 MvcRepository"
Ergänzung ()

@holy: Was meinst du mit Name teilen?
 
mosquito87 schrieb:
Ergänzung ()

@holy: Was meinst du mit Name teilen?

Ob es in deinem Projekt zwei Interfaces mit dem Namen ISqlEntity gibt?
Es muss nichtmals sein, dass du so clever warst, evtl. exportiert eine deiner Referenzen dieses Interface. Einfach mal den Namespace von deinem ISqlEntity Argument prüfen.
Wenn es das auch nicht ist, dann keine Ahnung.
 
Spring per Druck auf F12 mal zur Definition deiness ISQLEntity-Interfaces. Springt er in zur von dir erwartetetn Quellcode-Datei?
 
Ok.
Es liegt an meinen Generics.

Momentan habe ich:
Code:
public abstract class Repository<IEntity>

und

Code:
public abstract class SqlRepository<ISqlEntity> : Repository<ISqlEntity>

Ich will quasi erreichen, dass ein erzeugen eines Repository-Objekts nur mit einer Klasse möglich ist, die das IEntity Interface nutzt.
Das Erzeugen eines SqlRepositories soll nur möglich sein, wenn die Klasse das ISqlEntity Interface nutzt (unabhängig davon, dass man keine Objekte abstrakter Klassen erzeugen kann).

Wie würde das denn korrekt aussehen?
 
Das dürfte hefen

Code:
    public interface IRepository<T>
    {
    }

    public abstract class Repositor<T> : IRepository<T> where T : IEntity
    {
    }

    public abstract class SqlRepository<T> : IRepository<T> where T : ISqlEntity
    {
    }

EDIT: Wobei auch Objekte Typ ISqlEntity an das Repository<T> übergeben werden können.

Hier wäre es von Vorteil, wenn Du für jeden EntityType ein eigenes Interface oder eine Base Class (Abstrakte Klasse) erstellst und diese als Constrains in where - Klausel angibst.

Code:
public interface ISqlEntity : IEntity { }

public abstract class BaseEntity : IEntity { }

public abstract class BaseSqlEntity : ISqlEntity { }

// und dann 
where T : BaseEntity
where T : BaseSqlEntity
 
Zuletzt bearbeitet:
Danke.

So hat alles geklappt:

Die Interfaces:

Code:
public interface IEntity

Code:
public interface ISqlEntity : IEntity

Die 2 Klassen:

Code:
public abstract class Repository<T> where T : IEntity

Code:
public abstract class SqlRepository<T> : Repository<T> where T : ISqlEntity

Ihr seid spitze! :D
 
Nein.
Eben erst.
Danke für den Hinweis.

Wenn ich dich richtig verstehe ist es so, dass an

Code:
public abstract class Repository<T> where T : IEntity

nicht nur IEntity sondern auch ISqlEntity übergeben werden kann, da ISqlEntity von IEntity erbt. Richtig?
Ich denke, dass ich damit leben könnte.
Gerade weil die Klassen ja abstrakt sind.
Mit weiteren abstrakten Klassen würde ich die Hierarchie verkomplizieren.
Oder hältst du das für sinnvoll?

Noch ein kleines Problem.
Ich hab eine weitere Unterklasse:
Code:
public class TaskSqlRepository<T> : SqlRepository<T> where T : Task

Die Klasse Task implementiert das Interface ISqlEntity.

Code:
protected override T getObject(SqlDataReader reader)
        {
            ...

            T task;
            task = new Task(id, number, description);

            return task;
        }

Die Methode funktioniert aber nicht:
"Cannot implicitly convert type 'MvcRepository.Models.Task' to 'T'. An explicit conversion exists (are you missing a cast?)".
Woran liegt das?
Task ist doch T!?
 
mosquito87 schrieb:
Nein.
Eben erst.
Danke für den Hinweis.

Wenn ich dich richtig verstehe ist es so, dass an

Code:
public abstract class Repository<T> where T : IEntity

nicht nur IEntity sondern auch ISqlEntity übergeben werden kann, da ISqlEntity von IEntity erbt. Richtig?
Korrekt.

mosquito87 schrieb:
Code:
public class TaskSqlRepository<T> : SqlRepository<T> where T : Task

Die Klasse Task implementiert das Interface ISqlEntity.

Code:
Die Methode funktioniert aber nicht:
"Cannot implicitly convert type 'MvcRepository.Models.Task' to 'T'. An explicit conversion exists (are you missing a cast?)".
Woran liegt das?
Task ist doch T!?[/QUOTE]

Task ist aber auch eine Klasse aus dem Namensraum System.Threading.Tasks (ab .NET 4).
Leitet dein Task auch von der ISqlEntity ab.

In persönlich würde in den Ableitungen nicht so tief gehen bzw. versuche ich, diese zu umgehen.
 
Wieso den so kompliziert machen.... man kann doch mehrere Interfaces an eine Klasse weitergeben. Wieso diese komische verkettung? Und ja du musst entity benutzen anstatt task. Sonst kann du einfach virual Methoden einbauen und diese dann in deine Hauptklasse überschreiben.
 
Zurück
Oben