Hi, wahrscheinlich tue ich mich gerade einfach viel zu schwer für dieses einfache Problem:
Ich möchte Daten aus Listen verarbeiten, die in verschiedenen Listeneinträgen abgelegt sind. Die bisherige Lösung ist aktuell, dass ich per LinQ und Select zuerst einmal die einzelnen Eigenschaften in eine Liste packe und die an meine Methode übergebe. Also so in etwa:
class Class A
{
public string Name { get; set;}
...
}
List<ClassA> listA = new List<ClassA>() { new ClassA() {....},...};
List<string> names = listA.Select(ca => ca.Name);
var tmp = DoSomething(names);
Mein Wunsch wäre jetzt das Ganze universeller und ohne die temporären Listen machen zu können also in etwa so:
List<ClassA> listA = new List<ClassA>() { new ClassA() {....},...};
var tmp = DoSomething( listA, "Name");
Wenn ich Reflections nutzen wollen würde wäre das machbar und man findet einige Lösungen dazu aber das muss doch auch eleganter und performanter machbar sein.
List<string> names = listA.Select(ca => ca.Name);
Das wird so nicht funktionieren, die Select-Methode gibt ein IEnumerable zurück 😛
Da wird also auch nichts kopiert oder eine neue Liste erstellt. Hast Du hier ein ToList vergessen? Das brauchst Du nicht, wenn Du direkt IEnumerable verwendest.
Warum willst Du das denn in die Methode rein ziehen? Sind vor dem Select noch andere LINQ-Aufrufe (z.B. Where) nötig, die sich immer wiederholen?
Wenn nicht, würde ich das so lassen, Du baust dir sonst auf lange Sicht nur eine hässlichere Variante von LINQ nach.
Aber wenn Du das aber unbedingt haben willst:
var tmp = DoSomething(listA, a => a.Name);
object DoSomething<TSource, TValue>(IEnumerable<TSource> source, Func<TSource, TValue> getValue)
{
var data = source.Select(getValue);
// ...
}
Mir wäre es so lieber, damit bin ich flexibler:
var tmp = DoSomething(listA.Select(a => a.Name));
object DoSomething<T>(IEnumerable<T> source)
{
// ...
}
PS:
Der Code ist direkt im Browser getippt, verzeiht eventuelle Fehler.
NuGet Packages im Code auslesen
lock Alternative für async/await
Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.
Meine erste Frage wäre, was ist der Zweck des Ganzen?
Willst du dir Tipparbeit ersparen oder soll hier ein spezifischer Zweck abgedeckt werden?
Mit Reflections sollte man arbeiten, wenn man weiß was man macht.
Mir ist auch nicht klar, in wie weit der gewünschter Ansatz den Code lesbar machen soll.
Damit würdest du die Funktion deines Codes mehr verschleiern als es nützt.
Deine Daten in einer Klasse zu kapseln ist absolut im Sinne der OOP.
Dies zu verwerfen würde die Lesbarkeitverschlechtern, da niemand außer dir verstehen kann warum dort der Code umgesetzt ist wie er aktuell ist.
Wenn du den Code in 1-2 Jahren oder gar Monaten mal wieder verstehen willst, machst du es dir damit extra schwer.
T-Virus
Developer, Developer, Developer, Developer....
99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
List<string> names = listA.Select(ca => ca.Name);
Das wird so nicht funktionieren, die Select-Methode gibt ein IEnumerable zurück 😛
Da wird also auch nichts kopiert oder eine neue Liste erstellt. Hast Du hier ein ToList vergessen? Das brauchst Du nicht, wenn Du direkt IEnumerable verwendest.
Ja, das habe ich vergessen. Aber direkt IEnumerable zu nutzen macht Sinn.
Warum willst Du das denn in die Methode rein ziehen? Sind vor dem Select noch andere LINQ-Aufrufe (z.B. Where) nötig, die sich immer wiederholen?
Wenn nicht, würde ich das so lassen, Du baust dir sonst auf lange Sicht nur eine hässlichere Variante von LINQ nach.Aber wenn Du das aber unbedingt haben willst:
var tmp = DoSomething(listA, a => a.Name); object DoSomething<TSource, TValue>(IEnumerable<TSource> source, Func<TSource, TValue> getValue) { var data = source.Select(getValue); // ... }
Danke! Genau sowas habe ich gesucht, Func zu nutzen statt über die PorpertyInfo zu gehen.
Mir wäre es so lieber, damit bin ich flexibler:
var tmp = DoSomething(listA.Select(a => a.Name)); object DoSomething<T>(IEnumerable<T> source) { // ... }
Meine erste Frage wäre, was ist der Zweck des Ganzen?
Willst du dir Tipparbeit ersparen oder soll hier ein spezifischer Zweck abgedeckt werden?
Mit Reflections sollte man arbeiten, wenn man weiß was man macht.Mir ist auch nicht klar, in wie weit der gewünschter Ansatz den Code lesbar machen soll.
Damit würdest du die Funktion deines Codes mehr verschleiern als es nützt.
Deine Daten in einer Klasse zu kapseln ist absolut im Sinne der OOP.
Dies zu verwerfen würde die Lesbarkeitverschlechtern, da niemand außer dir verstehen kann warum dort der Code umgesetzt ist wie er aktuell ist.
Wenn du den Code in 1-2 Jahren oder gar Monaten mal wieder verstehen willst, machst du es dir damit extra schwer.
Es sind viele Properties (ca. 50) die jeweils in zwei Listen des gleichen Typs vorhanden sind und auf die die Methode angewandt wird.
Real sieht das dann eher so aus:
List<ClassA> valuesForward0 = listAForward.Select(ca => ca.Property0).ToList();
List<ClassA> valuesBackward0 = listABackward.Select(ca => ca.Property0).ToList();
result0 = DoSomething(valuesForward0, valuesBackward0, defaultValue0);
Das 5 zig mal ist nicht unbedingt übersichtlich und jedesmal die temporären Listen zu erstellen ist imho auch nicht sehr übersichtlich. Da ist die Variante doch deutlich angenehmer:
result0 = DoSomething(listAForward, listABackward, ca => ca.Property0, defaultValue0);
Nun, da - und da kann man sicher hervorragend drüber streiten - würde ich doch Reflection in Betracht ziehen, zumindest wenn es immer alle Properties der Klasse sind.
Dann würde ich aber eine zweite Methode schreiben, die alle Properties der Klasse durch läuft und einzeln die erste Methode aufruft. Je nachdem, worum es da geht, hat das den Vorteil, dass Du keine Properties vergessen kannst.
NuGet Packages im Code auslesen
lock Alternative für async/await
Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.
Reflection:
Einzelaufruf pro Property:
Kurz gesagt: entscheide dich zwischen Compiletime- oder Runtime-Fehlern. Ich müsste da nicht allzu lange nachdenken.
LaTino
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
Es werden nicht immer alle Properties der Klasse genutzt und teilweise die gleiche Methode später noch mal aufgerufen, daher wird das per Reflections wohl nicht so schön.
Ein weitere Vorteil ist für mich speziell, da es sich fast durchgängig um double-Werte handelt, dass eine teilweise notwendige Skalierung direkt mit im Aufruf ersichtlich wird (so wie es aktuell beim erzeugen der temporären Listen auch ist). Via Reflections müsste diese dann ja zusätzlich übergeben werden.
Auf jeden Fall allen schon mal einen herzlichen Dank für die schnellen Antworten und konstruktive Diskussiopn! 👍