OfType et Cast
Vous est-il déjà arrivé de vouloir utiliser Linq sur une liste ou une collection qui ne supporte pas Linq?
Je peux prendre l’exemple de l’ArrayList qui ne le permet pas.
Il existe malgré tout un moyen de contourner ce problème via deux méthodes d’extension : OfType et Cast.
Ces deux méthodes sont disponibles depuis la version 3.5 du Framework .Net.
Elles renvoient toutes les deux un IEnumerable qui supporte Linq mais ne fonctionnent pas de la même manière.
Là où OfType filtre par type d’objet, Cast quand à lui transforme les objets suivant le type fourni.
OfType
Prenons notre ArrayList tel que défini ci-dessous :
ArrayList arrayList = new ArrayList();
arrayList.Add(
new WebCustomer
{
FirstName = "Bob",
LastName = "Morane",
Website = @"http://nicolas-cousin.com/"
});
arrayList.Add(
new WebCustomer
{
FirstName = "Morgan",
LastName = "Freeman",
Website = @"http://nicolas-cousin.com/"
});
arrayList.Add(
new LiveCustomer
{
FirstName = "Liv",
LastName = "Boree",
ShopName = @"Mon Magasin Live"
});
arrayList.Add(
new BlogArticle
{
Title = "OfType et Cast"
});
Et utilisons OfType pour afficher les informations suivant leur type :
arrayList.OfType<WebCustomer>().ToList().ForEach(c =>
{
Console.WriteLine("{0} {1} {2}", c.FirstName, c.LastName, c.Website);
});
arrayList.OfType<LiveCustomer>().ToList().ForEach(c =>
{
Console.WriteLine("{0} {1} {2}", c.FirstName, c.LastName, c.ShopName);
});
arrayList.OfType<Customer>().ToList().ForEach(c =>
{
Console.WriteLine("{0} {1}", c.FirstName, c.LastName);
});
arrayList.OfType<BlogArticle>().ToList().ForEach(c =>
{
Console.WriteLine("{0}", c.Title);
});
Voici le résultat :
Explication :
OfType à filtré le résultat par type d’objet : WebCustomer et LiveCustomer qui héritent de Customer tous les deux ce qui explique la troisième requête.
Cast
Si nous essayons de faire l’une de ces requêtes en utilisant Cast à la place nous aurons une erreur car Cast cherche a tout transformer dans le type demandé.
Modifions notre liste pour retirer le BlogArticle :
ArrayList arrayList = new ArrayList();
arrayList.Add(
new WebCustomer
{
FirstName = "Bob",
LastName = "Morane",
Website = @"http://nicolas-cousin.com/"
});
arrayList.Add(
new WebCustomer
{
FirstName = "Morgan",
LastName = "Freeman",
Website = @"http://nicolas-cousin.com/"
});
arrayList.Add(
new LiveCustomer
{
FirstName = "Liv",
LastName = "Boree",
ShopName = @"Mon Magasin Live"
});
Vérifions la requête suivante :
arrayList.Cast<WebCustomer>().ToList().ForEach(c =>
{
Console.WriteLine("{0} {1} {2}", c.FirstName, c.LastName, c.Website);
});
Résultat :
Une exception du type System.InvalidCastException est levée.
Vérifions ensuite la requête :
arrayList.Cast<LiveCustomer>().ToList().ForEach(c =>
{
Console.WriteLine("{0} {1} {2}", c.FirstName, c.LastName, c.ShopName);
});
Résultat :
Une exception du type System.InvalidCastException est levée.
Vérifions pour finir la requête :
arrayList.Cast<Customer>().ToList().ForEach(c =>
{
Console.WriteLine("{0} {1}", c.FirstName, c.LastName);
});
Résultat :
Conclusion
Dans l’utilisation des deux méthodes, il faut distinguer leur mode de fonctionnement.
OfType va donc filtrer pour ne sortir que les éléments correspondant au type demandé.
Cast va essayer de transformer tous les objets dans le type demandé et provoquerai une erreur s’il ne peut pas le faire pour un élément.