Laden...

Funktionsaufruf mittels Templateobjekt

Erstellt von Stone1984 vor 3 Jahren Letzter Beitrag vor 3 Jahren 429 Views
S
Stone1984 Themenstarter:in
7 Beiträge seit 2020
vor 3 Jahren
Funktionsaufruf mittels Templateobjekt

Guten Abend,

seit einigen Stunden bin ich schon dabei eine Lösung für einen Funktionsaufruf von einem Template (Generic) objekt ausgehend. Leider bekomme ich dabei den Fehler:

"TList enthält keine Funktion update"

Der zugrundeliegende Code sieht folgendermaßen aus:
Das Hauptprogramm ist:


MySQLDataList<CompanyList> companies = new MySQLDataList<CompanyList>();
companies.createEmptyObject();
companies.getDataList().data.Add(new Company { ID = 1, NAME = "Firma 1" });
companies.getDataList().data.Add(new Company { ID = 2, NAME = "Firma 2" });
companies.getDataList().data.Add(new Company { ID = 3, NAME = "Firma 3" });
companies.getDataList().data.Add(new Company { ID = 4, NAME = "Firma 4" });
CompanyList companyList = companies.getDataList();

CompanyList tempCompany = new CompanyList();
tempCompany.data.Add(new Company { ID = 2, NAME = "Firma 5" });
companies.update(tempCompany);

und die Klasse CompanyList ist:


class CompanyList
{
    public CompanyList()
    {
        data = new List<Company>();
    }

    public List<Company> data { get; set; }

    public void update(CompanyList a_companyList)
    {
        for (int i = 0; i < a_companyList.data.Count; i++)
        {
            update(a_companyList.data[i]);
        }
    }

    /**
     * \brief       Update eines Datensatzes.
     * \param[in]   Datensatz der geupdated werden soll.
     */
    public void update(Company a_company)
    {
        for (int i = 0; i < data.Count; i++)
        {
            if (data[i].ID == a_company.ID)
            {
                data[i].NAME = a_company.NAME;
            }
        }
    }
}

public class Company
{
    public int ID { get; set; }
    public string NAME { get; set; }
}

und schließlich die Klasse MySQLDataList:


class MySQLDataList<TList>
{
    public MySQLDataList()
    {
            
    }

    public void update(TList a_dataList)
    {
        m_dataList.update(a_dataList);
    }

    public void createEmptyObject()
    {
        m_dataList = new JavaScriptSerializer().Deserialize<TList>("{\"data\":[]}");
    }

    public TList getDataList()
    {
        return m_dataList;
    }

    TList m_dataList = default(TList);          //!< Liste mit Daten aus der Datenbank.
}

Probleme macht mir in dieser Klasse der Aufruf:


m_dataList.update(a_dataList);

Ich bin davon ausgegangen, da sich m_dataList in diesem Template vom Typ CompanyList ist und CompanyList die Funktion update besitzt, dass dieser Aufruf möglich wäre. Für mein TList ist sichergestellt, das jede Klasse, die für TList übergeben wird eine update-Methode enthält.

Kennt jemand eine Möglichkeit, wie ich in dem vorliegenden Programm einen gültigen Aufruf von update, ausgehend vom Objekt TList erzeugen kann? Gibt es evtl. in C# anderweitige Methoden, mit denen ich derartige generische Aufrufe realisieren kann?

Bei meiner Such bin ich bisher leider auf nichts vergleichbares gestoßen.

J
61 Beiträge seit 2020
vor 3 Jahren

Mir fehlt das Interface das die Funktion „update“ enthält und das auch für TList als Einschränkung definiert ist und daher auch für CompanyList implementiert sein muss.

Siehe auch https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/generic-interfaces.

S
Stone1984 Themenstarter:in
7 Beiträge seit 2020
vor 3 Jahren

Vielen Dank für den Hinweis. Das bedeutet, das ich zur Klasse CompanyList folgenden Code hinzufügen muss:


interface IListInterface<TList>
{
    void update(TList a_companyList);
}

class CompanyList : IListInterface<CompanyList>
{
......

Nur wie mache ich es dann in der Klasse MySQLDataList? Auf dieser Seite funktioniert es bei mir noch nicht.

P
441 Beiträge seit 2014
vor 3 Jahren

Was du da machst sieht schon sehr abenteuerlich und kompliziert aus.

Du kommst von PHP - richtig? Schau dir am besten die Grundlagen und Pattern von C# an.

Zu deinem Problem:
Aktuell kann jeglicher Typ als TList genutzt werden. Wenn du dort eine update-Methode haben willst, musst du den Typen einschränken, auf entweder einen Typen, der update implementiert hat oder ein Interface, dass dieses vorschreibt.
Das geht über Generic Constraints.

Edit: oh sorry.. exakt der gleiche Link 😃
Einfach nochmal den Link durchlesen... den Punkt mit dem where ...

S
Stone1984 Themenstarter:in
7 Beiträge seit 2020
vor 3 Jahren

@Papst: Vielen Dank für den Hinweis mit dem where. Nachdem ich die Zeile


class MySQLDataList<TList> where TList : IListInterface<TList>

in MySQLDataList ergänzt hatte läuft es einwandfrei und eröffnet neue Möglichkeiten.

Bin übrigends hauptsächlich aus der hardwarenahen C++ Welt. Bastelle aber nebenbei auch mit PHP, SQL und C# an Anwendungen herum.

16.835 Beiträge seit 2008
vor 3 Jahren

Bin übrigends hauptsächlich aus der hardwarenahen C++ Welt.

Das sieht man an Deinen Bezeichnern wie a_, Uppercase-Properties und Co; typisch aus der C++ Welt 😉
Macht man in C# jedoch weniger bis gar nicht.

Nur als Hinweis: [Artikel] C#: Richtlinien für die Namensvergabe