How can I implement NotOfType in LINQ that has a nice calling syntax?

前端 未结 7 1159
轻奢々
轻奢々 2020-12-11 00:24

I\'m trying to come up with an implementation for NotOfType, which has a readable call syntax. NotOfType should be the complement to OfType&l

相关标签:
7条回答
  • 2020-12-11 00:45

    I am not sure why you don't just say:

    animals.Where(x => !(x is Giraffe));
    

    This seems perfectly readable to me. It is certainly more straight-forward to me than animals.NotOfType<Animal, Giraffe>() which would confuse me if I came across it... the first would never confuse me since it is immediately readable.

    If you wanted a fluent interface, I suppose you could also do something like this with an extension method predicate on Object:

    animals.Where(x => x.NotOfType<Giraffe>())
    
    0 讨论(0)
  • 2020-12-11 00:47

    This might seem like a strange suggestion, but what about an extension method on plain old IEnumerable? This would mirror the signature of OfType<T>, and it would also eliminate the issue of the redundant <T, TExclude> type parameters.

    I would also argue that if you have a strongly-typed sequence already, there is very little reason for a special NotOfType<T> method; it seems a lot more potentially useful (in my mind) to exclude a specific type from a sequence of arbitrary type... or let me put it this way: if you're dealing with an IEnumerable<T>, it's trivial to call Where(x => !(x is T)); the usefulness of a method like NotOfType<T> becomes more questionable in this case.

    0 讨论(0)
  • 2020-12-11 00:49

    If you're going to make a method for inference, you want to infer all the way. That requires an example of each type:

    public static class ExtMethods
    {
        public static IEnumerable<T> NotOfType<T, U>(this IEnumerable<T> source)
        {
            return source.Where(t => !(t is U));
        }
          // helper method for type inference by example
        public static IEnumerable<T> NotOfSameType<T, U>(
          this IEnumerable<T> source,
          U example)
        {
            return source.NotOfType<T, U>();
        }
    }
    

    called by

    List<ValueType> items = new List<ValueType>() { 1, 1.0m, 1.0 };
    IEnumerable<ValueType> result = items.NotOfSameType(2);
    
    0 讨论(0)
  • 2020-12-11 00:56

    I had a similar problem, and came across this question whilst looking for an answer.

    I instead settled for the following calling syntax:

    var fewerAnimals = animals.Except(animals.OfType<Giraffe>());
    

    It has the disadvantage that it enumerates the collection twice (so cannot be used with an infinite series), but the advantage that no new helper function is required, and the meaning is clear.

    In my actual use case, I also ended up adding a .Where(...) after the .OfType<Giraffe>() (giraffes also included unless they meet a particular exclusion condition that only makes sense for giraffes)

    0 讨论(0)
  • 2020-12-11 00:56

    I've just tried this and it works...

    public static IEnumerable<TResult> NotOfType<TExclude, TResult>(this IEnumerable<TResult> sequence)
        => sequence.Where(x => !(x is TExclude));
    

    Am I missing something?

    0 讨论(0)
  • 2020-12-11 01:00

    How about

    animals.NotOf(typeof(Giraffe));
    

    Alternatively, you can split the generic parameters across two methods:

    animals.NotOf().Type<Giraffe>();
    
    public static NotOfHolder<TSource> NotOf<TSource>(this IEnumerable<TSource> source);
    
    public class NotOfHolder<TSource> : IHideObjectMembers {
        public IEnumerable<TSource> NotOf<TNot>();
    }
    

    Also, you need to decide whether to also exclude inherited types.

    0 讨论(0)
提交回复
热议问题