Do we have a "Contains" method in IEnumerable - c#

I have a class in my code that is already deriving from IEnumerable.
I was wondering if there is a way that I can use a "Contains" method on its instnaces to look for a something in that list?

Do you really implement the non-generic IEnumerable, or the generic IEnumerable<T>? If you can possibly implement the generic one, your life will become a lot simpler - as then you can use LINQ to Objects, which does indeed have a Contains extension method.
Otherwise, you could potentially convert from the non-generic to generic using Cast or OfType, e.g.
bool found = nonGeneric.Cast<TargetType>().Contains(targetItem);
It would be nicer if you just implemented the generic interface to start with though :)

No, there's no such method in the IEnumerable<T> interface. There's an extension method though that you could use.
using System.Linq;
and then:
IEnumerable<string> foos = new[] { "foo", "bar", "baz" };
bool IsThereABar = foos.Contains("bar");

public static bool Contains<T>(this IEnumerable source, T value)
{
foreach (var i in source)
{
if (Equals(i, value))
return true;
}
return false;
}
If you want, you can add custom comparer as parameter ti extension method Contains

Related

C# : Method having IEnumerable<Type> as argument. What is a valid input?

I am trying to define a valid input for my method Pairwise. Pairwise takes an argument IEnumerable which I am having trouble figuring out what is exactly. I have tried alot of stuff but can never really get there.
public delegate void PairwiseDel(Type left, Type right);
public static void Pairwise(IEnumerable<Type> col, PairwiseDel del)
{
// stuff happens here which passes pairs from col to del
}
can someone plz tell and illustrate what a valid input for my method would be?
IEnumerable<T> is a very important interface in .NET library. It represents an abstraction describing a sequence of elements of type T.
This generic interface has multiple implementations:
Built-in 1-dimension arrays T[] implement IEnumerable<T>
All generic .NET collections implement IEnumerable<T>
Methods that use yield return produce IEnumerable<T>
Multiple methods in .NET LINQ library both take and return IEnumerable<T>
If you would like to test your method, pass it an array Type[]:
var items = new Type[] { typeof(int), typeof(string), typeof(long) };
Pairwise(items, (a, b) => {
Console.WriteLine("A={0}, B={1}", a.Name, b.Name);
});
This would be a valid input:
var collection = new List<Type>();
collection.Add(typeof(string));
collection.Add(typeof(int));
PairWise(collection, YourDelegateHere);

Where is the ToList() method? (IQueryable)

If I try this, it will work:
var query = myContextObject.Users.Where(u=>u.Name == "John");
query.ToList();
I'm able to call ToList and a lot of other extension methods.
But if I try this:
public List ConvertQueryToList(IQueryable query)
{
return query.ToList();
}
ToList won't be accessible, I'm guessing this is because ToList is an extension method, but then how is that ToList is attached in the first example?
Is it possible to access ToList in the second case?
You need to write it as:
public List<T> ConvertQueryToList<T>(IQueryable<T> query)
{
return query.ToList();
}
This will cause the IQueryable<T> to return the appropriate List<T>, since the Enumerable.ToList() method requires an IEnumerable<T> as input (which also works with IQueryable<T>, as IQueryable<T> inherits IEnumerable<T>).
That being said, there is really no reason to use it this way. You can always just call ToList() directly if you need to create a List<T> - abstracting inside of a second layer just confuses the API further.
If you're trying to convert a non-generic IQueryable interface, you would need to do something like:
public List<T> ConvertQueryToList<T>(IQueryable query)
{
return query.Cast<T>.ToList();
}
This would then require calling like:
var results = ConvertQueryToList<SomeType>(queryable);
Alternatively, if you want to leave this non-generic (which I wouldn't recommend), then you could use:
public ArrayList ConvertQueryToList(IQueryable query)
{
ArrayList results = new ArrayList();
results.AddRange(query.Cast<object>().ToList());
return results;
}
The first of your examples returns an IQueryable<T>, whereas in the second you're using IQueryable (without the Generic Type parameter).
You can check out the two completely different interfaces here and here.
Here is an extension method for this:
public static class ListHelper
{
public static IList ToList(this IQueryable query)
{
var genericToList = typeof(Enumerable).GetMethod("ToList")
.MakeGenericMethod(new Type[] { query.ElementType });
return (IList)genericToList.Invoke(null, new[] { query });
}
}
Here is a generic extension method for the case you are using IQueryable<>.
Of course it is not absolutely safe because the type could be wrong and the cast could fail. So please be careful if you use that method.
using System.Collections.Generic;
namespace System.Linq
{
public static class Extensions
{
public static List<T> ToList<T>(this IQueryable queriable)
{
return ((IQueryable<T>)queriable).ToList();
}
}
}

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

I'm trying to come up with an implementation for NotOfType, which has a readable call syntax. NotOfType should be the complement to OfType<T> and would consequently yield all elements that are not of type T
My goal was to implement a method which would be called just like OfType<T>, like in the last line of this snippet:
public abstract class Animal {}
public class Monkey : Animal {}
public class Giraffe : Animal {}
public class Lion : Animal {}
var monkey = new Monkey();
var giraffe = new Giraffe();
var lion = new Lion();
IEnumerable<Animal> animals = new Animal[] { monkey, giraffe, lion };
IEnumerable<Animal> fewerAnimals = animals.NotOfType<Giraffe>();
However, I can not come up with an implementation that supports that specific calling syntax.
This is what I've tried so far:
public static class EnumerableExtensions
{
public static IEnumerable<T> NotOfType<T>(this IEnumerable<T> sequence, Type type)
{
return sequence.Where(x => x.GetType() != type);
}
public static IEnumerable<T> NotOfType<T, TExclude>(this IEnumerable<T> sequence)
{
return sequence.Where(x => !(x is TExclude));
}
}
Calling these methods would look like this:
// Animal is inferred
IEnumerable<Animal> fewerAnimals = animals.NotOfType(typeof(Giraffe));
and
// Not all types could be inferred, so I have to state all types explicitly
IEnumerable<Animal> fewerAnimals = animals.NotOfType<Animal, Giraffe>();
I think that there are major drawbacks with the style of both of these calls. The first one suffers from a redundant "of type/type of" construct, and the second one just doesn't make sense (do I want a list of animals that are neither Animals nor Giraffes?).
So, is there a way to accomplish what I want? If not, could it be possible in future versions of the language? (I'm thinking that maybe one day we will have named type arguments, or that we only need to explicitly supply type arguments that can't be inferred?)
Or am I just being silly?
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>())
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.
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.
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);
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)
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?
You might consider this
public static IEnumerable NotOfType<TResult>(this IEnumerable source)
{
Type type = typeof(Type);
foreach (var item in source)
{
if (type != item.GetType())
{
yield return item;
}
}
}

How to call a generic extension method dynamically?

I wrote this extension method:
public static DataTable ToDataTable<T>(this IList<T> list)
{...}
It works well if called with a type known at compile time:
DataTable tbl = new List<int>().ToDataTable();
But how to call it if the generic type isn't known?
object list = new List<int>();
...
tbl = Extension.ToDataTable((List<object>)list); // won't work
This occurs because a List<int> is not a List<object> -- the List type is not covariant in its element type parameter. Unfortunately you would need to get a typed version of the generic method and call it using reflection:
Type listItemType = typeof(int); // cheating for simplicity - see below for real approach
MethodInfo openMethod = typeof(Extension).GetMethod("ToDataTable", ...);
MethodInfo typedMethod = openMethod.MakeGenericMethod(typeof(listItemType));
typedMethod.Invoke(null, new object[] { list });
An alternative may be to create a version of your extension method that accepts IList rather than IList<T>. The List<T> class implements this non-generic interface as well as the generic interface, so you will be able to call:
public static DataTable WeakToDataTable(this IList list) { ... }
((IList)list).WeakToDataTable();
(In reality you'd probably use an overload rather than a different name -- just using a different name to call out the different types.)
More info: In the reflection solution, I skipped over the problem of how to determine the list element type. This can be a bit tricky depending on how sophisticated you want to get. If you're assuming that the object will be a List<T> (for some T) then it's easy:
Type listItemType = list.GetType().GetGenericArguments()[0];
If you're only willing to assume IList<T> then it's a bit harder, because you need to locate the appropriate interface and get the generic argument from that. And you can't use GetInterface() because you're looking for a closed constructed instance of a generic interface. So you have to grovel through all the interfaces looking for one which is an instance of IList<T>:
foreach (Type itf in list.GetType().GetInterfaces())
{
if (itf.IsGenericType && itf.GetGenericTypeDefinition == typeof(IList<>)) // note generic type definition syntax
{
listItemType = itf.GetGenericArguments()[0];
}
}
This will work for empty lists because it goes off the metadata, not the list content.
After having trouble to get it working with the IList<T> interface I solved it using the IList interface like itowlson proposed. It's a little bit ugly because of the _T method but it works well:
DataTable tbl = ((IList)value).ToDataTable();
public static class Extensions
{
private static DataTable ToDataTable(Array array) {...}
private static DataTable ToDataTable(ArrayList list) {...}
private static DataTable ToDataTable_T(IList list) {...}
public static DataTable ToDataTable(this IList list)
{
if (list.GetType().IsArray)
{
// handle arrays - int[], double[,] etc.
return ToDataTable((Array)list);
}
else if (list.GetType().IsGenericType)
{
// handle generic lists - List<T> etc.
return ToDataTable_T(list);
}
else
{
// handle non generic lists - ArrayList etc.
return ToDataTable((ArrayList)list);
}
}
}

Best way to convert IList or IEnumerable to Array

I have a HQL query that can generate either an IList of results, or an IEnumerable of results.
However, I want it to return an array of the Entity that I'm selecting, what would be the best way of accomplishing that? I can either enumerate through it and build the array, or use CopyTo() a defined array.
Is there any better way? I went with the CopyTo-approach.
Which version of .NET are you using? If it's .NET 3.5, I'd just call ToArray() and be done with it.
If you only have a non-generic IEnumerable, do something like this:
IEnumerable query = ...;
MyEntityType[] array = query.Cast<MyEntityType>().ToArray();
If you don't know the type within that method but the method's callers do know it, make the method generic and try this:
public static void T[] PerformQuery<T>()
{
IEnumerable query = ...;
T[] array = query.Cast<T>().ToArray();
return array;
}
Put the following in your .cs file:
using System.Linq;
You will then be able to use the following extension method from System.Linq.Enumerable:
public static TSource[] ToArray<TSource>(this System.Collections.Generic.IEnumerable<TSource> source)
I.e.
IEnumerable<object> query = ...;
object[] bob = query.ToArray();
I feel like reinventing the wheel...
public static T[] ConvertToArray<T>(this IEnumerable<T> enumerable)
{
if (enumerable == null)
throw new ArgumentNullException("enumerable");
return enumerable as T[] ?? enumerable.ToArray();
}
In case you don't have Linq, I solved it the following way:
private T[] GetArray<T>(IList<T> iList) where T: new()
{
var result = new T[iList.Count];
iList.CopyTo(result, 0);
return result;
}
Hope it helps

Categories