PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C# Lambda zu Delegate


Drexel
2010-03-24, 09:11:15
Ich habe hier eine Klasse movie. u.a. mit dem public member "created".


public class movie
{
...
public DateTime created {get; set;}
...
}


Die Klasse wurde über LINQ to SQL aus einer Datenbank erzeugt. Die Datenbank frage ich jetzt mit LINQ ab. Ich will alle movies abfragen und diese auch vom user sortieren lassen. Prinzipiell funktioniert das auch so (die SortExpression wird noch nicht vollständig ausgewertet):


public class MovieDAO
{
private mymdbDataContext mymdbDC = new mymdbDataContext();

public IQueryable<movie> GetMovies(int maximumRows, int startRowIndex, string SortExpression)
{
IQueryable<movie> movies = from m in this.mymdbDC.movie select m;

if (SortExpression != "")
{
movies = movies.OrderBy(mv => mv.internaltitle);
}
else
{
movies.OrderBy(mv => mv.created);
}

movies = movies.Skip(startRowIndex).Take(maximumRows);
return movies;
}
}


Zum besseren Verständnis meinerseits habe ich nun versucht, den Lambda Ausdruck mal in einen Delegate umzuwandeln:


public delegate DateTime GetMemberinfoDelegate (movie mv);

public class MovieDAO
{
private mymdbDataContext mymdbDC = new mymdbDataContext();

private DateTime getDT(movie mv)
{
return mv.created;
}

public IQueryable<movie> GetMovies(int maximumRows, int startRowIndex, string SortExpression)
{
IQueryable<movie> movies = from m in this.mymdbDC.movie select m;

if (SortExpression != "")
{
movies = movies.OrderBy(mv => mv.internaltitle);
}
else
{
GetMemberinfoDelegate del = this.getDT;
movies = movies.OrderBy(del);
}

movies = movies.Skip(startRowIndex).Take(maximumRows);
return movies;
}
}


Sollte meiner Meinung nach eigentlich das gleiche sein, aber das funktioniert nicht. Visual Studio meldet mir:

The type arguments for method 'System.Linq.Enumerable.OrderBy<TSource,TKey>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,TKey>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

Ich habs auch schon diverse andere Sachen probiert wie als Expresseion<T>, aber alles funktioniert nicht, nur wenn ich den Lambda Ausdruck direkt an OrderBy übergebe. Kann mir jemand sagen wieso bzw. was falsch ist?

Expandable
2010-03-24, 09:43:05
Probiers mal mit Func<Movie, DateTime> del = this.getDT.

Drexel
2010-03-24, 16:51:10
Funktioniert zwar, aber dann gibt movies.OrderBy(del) einen IOrderedEnumerable<movie> zurück, d.h. ich kann keine weiteren Einschränken mehr drauf ausführen, die bei IQueryable<movie> möglich wären...

Expandable
2010-03-25, 07:58:34
Also eigentich sollte das IOrderedQueryable zurückliefern: http://msdn.microsoft.com/en-us/library/bb549264%28v=VS.90%29.aspx. IOrderedQueryable erbt dann wiederum von IQueryable (http://msdn.microsoft.com/en-us/library/bb340178%28v=VS.90%29.aspx) und damit sollten alle LINQ-Funktionen wieder anwendbar sein.

Im übrigen kannst du IQueryable<movie> movies = from m in this.mymdbDC.movie select m;
einfach durch IQueryable<movie> moviews = this.mymdbDC.movie ersetzen.

Nachtrag: Ah, das Problem ist, dass du nicht Func<Movie, bool> verwenden darfst, sondern Expression<Func<Movie, bool>> (sonst wird die IEnumerable-Extensionmethode verwendet, die in der Tat IOrderedEnumerable zurückliefert). Also am besten: Einfach inline 'ne Lambda-Funktion verwenden :)

Drexel
2010-03-25, 09:03:26
Achso, ich glaub so langsam verstehe ich. Dass es eine Expression<T> das Argument sein muss, hatte ich auch schon gesehen. Also habe ich als einzige Möglichkeit die Expression selber zusammenzubauen (wo ich allerdings noch nicht ganz den Ruchblick habe), oder halt den Lambda Ausdruck zu verwenden, der automatisch in einen Expression Tree umgewandelt wird?

Expandable
2010-03-25, 14:41:32
Soweit ich weiß, ja.