Feedback

C# - Linq: Versuche Liste von X auf Liste von Y zu casten

Veröffentlicht von am 5/22/2015
(0 Bewertungen)
Die Linq-Extension .Cast<Result>() ist praktisch, wenn man eine Liste umwandeln will, wo garantiert alle Objekte nach TResult castbar sind.

Wenn das aber nicht der Fall ist, bekommt man die übliche InvalidCastException.

Wenn man aber wenigstens eine verkürzte Liste haben will, dann muss man es selbst machen:
/// <summary />
public static class CastHelper
{
    /// <summary>
    /// Returns a list of objects that could be cast to the given type.
    /// </summary>
    /// <typeparam name="TSource">the type of the list items</typeparam>
    /// <typeparam name="TResult">the type of the cast</typeparam>
    /// <param name="source">the original list</param>
    /// <returns>a list of successfully casted objects</returns>
    public static IEnumerable<TResult> TryCast<TSource, TResult>(this IEnumerable<TSource> source)
    {
        IEnumerable<TSource> filtered;
        IEnumerable<TResult> cast;

        if (source == null)
        {
            throw (new ArgumentNullException("source"));
        }

        filtered = source.Where(item => (item is TResult));

        cast = filtered.Cast<TResult>();

        return (cast);
    }

    /// <summary>
    /// Tries to cast the objects of a given list to a given type and returns the successfully and unsuccessfully casted objects in two lists.
    /// </summary>
    /// <typeparam name="TSource">the type of the list items</typeparam>
    /// <typeparam name="TResult">the type of the cast</typeparam>
    /// <param name="source">the original list</param>
    /// <param name="castedList">a list of successfully casted objects</param>
    /// <param name="uncastedList">a list of unsuccessfully casted objects</param>
    /// <param name="noNullsInUncastedList">determines if the uncastedList can contain null values</param>
    public static void TryCast<TSource, TResult>(this IEnumerable<TSource> source
        , out IEnumerable<TResult> castedList
        , out IEnumerable<TSource> uncastedList
        , Boolean noNullsInUncastedList = false)
    {
        if (source == null)
        {
            throw (new ArgumentNullException("source"));
        }

        castedList = source.TryCast<TSource, TResult>();

        uncastedList = source.GetUncastable<TSource, TResult>(noNullsInUncastedList);
    }

    /// <summary>
    /// Returns a list of objects that cannot be cast to the given type.
    /// </summary>
    /// <typeparam name="TSource">the type of the list items</typeparam>
    /// <typeparam name="TResult">the type of the cast</typeparam>
    /// <param name="source">the original list</param>
    /// <param name="noNullsInUncastedList">determines if the returned list can contain null values</param>
    /// <returns>a list of unsuccessfully casted objects</returns>
    public static IEnumerable<TSource> GetUncastable<TSource, TResult>(this IEnumerable<TSource> source
        , Boolean noNullsInUncastedList = false)
    {
        IEnumerable<TSource> filtered;

        if (source == null)
        {
            throw (new ArgumentNullException("source"));
        }

        filtered = source.Where(item => ((item is TResult) == false));

        if (noNullsInUncastedList)
        {
            filtered = filtered.Where(item => (item != null));
        }

        return (filtered);
    }
}


//Sample Code:

static class Program
{
    static void Main()
    {
        FilterAutos();

        Console.WriteLine();
        Console.WriteLine();

        FilterFahrzeuge();

        Console.WriteLine();
        Console.WriteLine();

        HardCast();

        Console.WriteLine();
        Console.WriteLine();

        NullAuto();

        Console.ReadLine();
    }

    private static void NullAuto()
    {
        Auto nullAuto = null;

        var zeugs = new List<object>() { new Audi(), nullAuto, new Ford(), new GrannySmith() };

        NullAuto(zeugs, true);

        Console.WriteLine();

        NullAuto(zeugs, false);

        Console.WriteLine();

        var autos = new List<Auto>() { new Audi(), nullAuto, new Ford() };

        NullAuto(autos, true);

        Console.WriteLine();

        NullAuto(autos, false);

        Console.WriteLine();
    }

    private static void NullAuto(List<object> zeugs
        , Boolean noNullsInUncastedList)
    {
        IEnumerable<Auto> fahrzeuge;
        IEnumerable<object> keineFahrzeuge;

        zeugs.TryCast(out fahrzeuge, out keineFahrzeuge, noNullsInUncastedList);

        Console.WriteLine("Fahrzeuge:");
        foreach (var fahrzeug in fahrzeuge)
        {
            Console.WriteLine(fahrzeug);
        }

        Console.WriteLine();

        Console.WriteLine("Keine Fahrzeuge:");
        foreach (var item in keineFahrzeuge)
        {
            Console.WriteLine(item);
        }
    }

    private static void NullAuto(List<Auto> zeugs
      , Boolean noNullsInUncastedList)
    {
        IEnumerable<Auto> fahrzeuge;
        IEnumerable<Auto> keineFahrzeuge;

        zeugs.TryCast(out fahrzeuge, out keineFahrzeuge, noNullsInUncastedList);

        Console.WriteLine("Fahrzeuge:");
        foreach (var fahrzeug in fahrzeuge)
        {
            Console.WriteLine(fahrzeug);
        }

        Console.WriteLine();

        Console.WriteLine("Keine Fahrzeuge:");
        foreach (var item in keineFahrzeuge)
        {
            Console.WriteLine(item);
        }
    }

    private static void FilterAutos()
    {
        var fahrzeuge = new List<Fahrzeug>() { new Audi(), new Ford(), new Harley() };

        IEnumerable<Auto> autos;

        autos = fahrzeuge.TryCast<Fahrzeug, Auto>();

        Console.WriteLine("Autos:");
        foreach (var auto in autos)
        {
            Console.WriteLine(auto);
        }
    }

    private static void FilterFahrzeuge()
    {
        var zeugs = new List<object>() { new Audi(), new GrannySmith(), new Harley() };

        IEnumerable<Fahrzeug> fahrzeuge;
        IEnumerable<object> keineFahrzeuge;

        zeugs.TryCast(out fahrzeuge, out keineFahrzeuge);

        Console.WriteLine("Fahrzeuge:");
        foreach (var fahrzeug in fahrzeuge)
        {
            Console.WriteLine(fahrzeug);
        }

        Console.WriteLine();

        Console.WriteLine("Keine Fahrzeuge:");
        foreach (var item in keineFahrzeuge)
        {
            Console.WriteLine(item);
        }
    }

    private static void HardCast()
    {
        var fahrzeuge = new List<Fahrzeug>() { new Audi(), new Ford(), new Harley() };

        IEnumerable<Auto> autos;

        autos = fahrzeuge.Cast<Auto>();

        Console.WriteLine("Autos:");
        try
        {
            foreach (var auto in autos)
            {
                Console.WriteLine(auto);
            }
        }
        catch (InvalidCastException ice)
        {
            Console.WriteLine(ice.Message);
        }
    }
}

abstract class Fahrzeug { }

abstract class Auto : Fahrzeug { }

class Audi : Auto { }

class Ford : Auto { }

abstract class Motorrad : Fahrzeug { }

class Harley : Motorrad { }

abstract class Apfel { }

class GrannySmith : Apfel { }
Abgelegt unter linq, cast, ienumerable.

1 Kommentare zum Snippet

Xilefius schrieb am 5/24/2015:
Die TryCast Methode gibt es bereits im Linq Namespace mit dem Namen "OfType". Kann genauso genutzt werden wie die Cast Extension, liefert aber nur Elemente des angegeben typs zurück
 

Logge dich ein, um hier zu kommentieren!