2017-07-19 1 views
-1

Ich habe eine Auflistung von Objekten, die nach dem Feldwert eines Objekts sortiert werden. Das aktuelle Problem ist, dass die Reihenfolge von einer Geschäftslogik abhängt.LINQ-Reihenfolge nach Delegat

public enum Order : byte { 
    a = 1, 
    b = 2, 
    c = 3 
} 

public class Foo{ 
    public long A {get;set;} 
    public long B {get;set;} 
    public long C {get;set;} 
} 

public class Worker(){ 
    private Foo[] orderFoos(Foo[] foos, Func<Order, long> sort){ 
     return foos.OrderByDescending(f => sort(f)).ToArray(foos.Length); 
    } 

    public void Work(){ 
     Foo[] foos = getFoos(); 

     var orderByA = orderFoos(foos, f => f.A); 
     var orderByB = orderFoos(foos, f => f.B); 
     var orderByC = orderFoos(foos, f => f.C); 
    } 
} 

Compiler wirft einen Fehler, dass Argument 1: cannot convert from 'Foo' to 'Order'. Gibt es Workarounds oder Lösungen?

+0

Welche Werte haben 'Foo.A',' Foo.B' und 'Foo.C'? – NtFreX

+0

@NtFreX '' 'long''', wird es in Foo-Klasse Erklärung erwähnt. – Max

+0

ich welche Werte und nicht welche Typen. Ich frage, weil ich nicht wirklich verstehe, was Sie versuchen zu tun. – NtFreX

Antwort

0

Der folgende Code scheint zu funktionieren. Es ist eine kleine Änderung an der orderFoos Methode, mit einigen Beispielcode für Sie, um die Ergebnisse zu testen.

using System; 
using System.Linq; 

public enum Order : byte 
{ 
    a = 1, 
    b = 2, 
    c = 3 
} 

public class Foo 
{ 
    public long A { get; set; } 
    public long B { get; set; } 
    public long C { get; set; } 
} 

public class Worker 
{ 
    private Foo[] orderFoos(Foo[] foos, Func<Foo, long> sort) 
    { 
     return foos.OrderByDescending(sort).ToArray(); 
    } 

    public void Work() 
    { 
     Foo[] foos = { new Foo() { A = 1, B = 2, C = 3 }, new Foo() { A = 10, B = 1, C = 2 }, new Foo() { A = -1, B = 1, C = 10 } }; 

     var orderByA = orderFoos(foos, f => f.A); 
     var orderByB = orderFoos(foos, f => f.B); 
     var orderByC = orderFoos(foos, f => f.C); 

     Console.WriteLine(orderByA.First().A); // I expect the second to be first here so 10 
     Console.WriteLine(orderByB.First().A); // I expect the first to be first here so 1 
     Console.WriteLine(orderByC.First().A); // I expect the third to be first here so -1 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var worker = new Worker(); 

     worker.Work(); 
     Console.ReadLine(); 
    } 
} 
+0

Nun, es ist genau was ich mit proxiing '' 'Order''' Parameter mache. – Max

1

Es scheint, dass Sie das Sortieren auf verschiedenen Feldern erreichen wollten. Sie können nicht bestellen Enum haben müssen, wenn sie zu diesem Zweck nur ist und ersetzt werden:

private Foo[] orderFoos(Foo[] foos, Func<Order, long> sort){ 
    return foos.OrderByDescending(f => sort(f)).ToArray(foos.Length); 
} 

in

private Foo[] orderFoos(Foo[] foos, Func<Foo, long> sort){ 
    return foos.OrderByDescending(sort).ToArray(foos.Length); 
} 

NB: Ich bin nicht sicher, dass Ihre Absicht mit foos.Length im ToArray Verfahren Hinzufügen , aber angeblich liegt das außerhalb der Reichweite der Frage.

+0

Ihre Lösung funktioniert nicht wie erwartet, aber sie hat mir ein besseres Verständnis dafür vermittelt, wie die Delegierten arbeiten. – Max

0

@hsoesanto gab eine gute Lösung, aber es funktioniert nicht so, wie ich es erwartet hätte.
So habe ich temporäre Abhilfe erstellt.

private Func<Foo, long> GetOrderFunction(Order orderType) 
{ 
    switch (orderType) 
    { 
     case Order.A: 
      return (f) => f.A; 
     case Order.B: 
      return (f) => f.B; 
     case Order.C: 
      return (f) => f.C; 
    } 
} 

private Foo[] orderFoos(Foo[] foos, Order order) 
{ 
    var orderFunction = GetOrderFunction(order); 
    return foos 
     .OrderByDescending(f => orderFunction (f)) 
     .ToArray(foos.Length); 
}