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.
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.
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.
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 ...
@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.
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
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code