Vem är Johan Lindfors

Jag är en passionerad utvecklare, arkitekt och tekniker, trivs med att presentera, demonstrera och implementera allt som har med programmeringa att göra. I den här bloggen har jag för avsikt att skriva om utveckling i allmänhet och på Microsofts plattform i synnerhet.

Är du intresserad av en XNA användargrupp?



Visa resultat!

Get Microsoft Silverlight

Widget Twitter not found.

Root element is missing.X

“Know thy LINQ”

LINQ är något som jag mycket gladeligen använder i mina applikationer, jag anser det vara ett tydligt och enkelt sätt att både filtrera och transformerera resultat precis på det sätt som applikationens aktuella tillstånd kräver.

Men det gäller att hålla tungan rätt i munnen, annars går det att åka på rejäla prestandaförluster, och här är ett exempel som jag hoppas är föga förvånande för just dig, men något som jag dessvärre har noterat i ett presentationsmaterial om just riktlinjer och rekommendationer.

Säg att du har en stor samling med data som du vill presentera i din applikation, och antagligen med en skräddarsydd vy-modell i förhållande till den vanliga data-modellen i applikationen.

class Person {
public int Age { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
}

class PersonViewModel
{
public int Age { get; set; }
public string Name { get; set; }
}

Låt mig sedan för enkelhetens skulle också skapa en statisk samling som jag kan filtrera och jobba med senare:

private static List<Person> _people = new List<Person>
{
new Person { Age = 4, Firstname = "Max", Lastname = "Lindfors" },
new Person { Age = 25, Firstname = "Johan", Lastname = "Lindfors" },
new Person { Age = 25, Firstname = "Lina", Lastname = "Lindfors" },
new Person { Age = 9, Firstname = "Matilda", Lastname = "Lindfors" },
};

Om jag sedan skapar en metod som kan användas för att projicera/transformera/anpassa modellen till vy-modellen så skulle den potentiellt kunna se ut så här:
 
private PersonViewModel GetPersonViewModel(Person person)
{
return new PersonViewModel {
Age = person.Age,
Name = string.Format("{0} {1}", person.Firstname, person.Lastname) };
}

Än så länge är det inga konstigheter hoppas jag. Transformering i det här fallet är enkel och tar inte mycket tid att processa. Nu finns det lite olika sätt att använda den här projiceringen på, och här är det första exemplet i LINQ:

var children = from p in _people
where p.Age < 18
select GetPersonViewModel(p);

Jag väljer i det här fallet att anropa projiceringen som “select” och får då en samling av vy-modeller tillbaka.

Ett alternativ är att istället explicit använda de “extensions” som bygger upp LINQ-språket, och det är då som det börjar bli intressant, här nedan följer två stycken kod-rader som resulterar samma resultat och samlingar, men med potentiellt helt olika resultat i prestanda för applikationen:

var children1 = _people.Select(GetPersonViewModel).Where(p => p.Age < 18);

var children2 = _people.Where(p => p.Age < 18).Select(GetPersonViewModel);

Den enda skillnaden på raderna ovan är naturligtvis ordningen på filtrering och projicering, vilken anser du vara korrekt och således bör den andra vara felaktig? Jag vill med det starkaste rekommendera det andra alternativet där filtreringen sker först och projiceringen efteråt, helt enkelt eftersom jag vill försöka anropa projiceringen så sällan som möjligt, speciellt om projiceringen är mer avancerad än i det här fallet. I “phoneBeat” hämtas ytterligare information från en lokal databas i vissa fall och då blir det naturligtvis ännu mer aktuellt att vara tydlig i ordningen. Tyvärr var det just det första alternativet som jag hittade i kod-exemplet och som fick mig att skriva det här lilla inlägget.

Att notera: Om du väljer att använda LINQ-uttrycket ovan så har åtminstone inte jag lyckats att få till ett “negativt” beteende eftersom det där just används ett “From-Where-Select”

Postades 23. maj 2011 10:43 av Johan Lindfors
Taggar:

Den här bloggen använder BlogEngine.NET 1.6.0.0
Temat anpassat av Johan Lindfors