Linq namespace and method any() - c#

So I am using System.Linq namespace and method Any() but for some reason it's shows me an error:
ArrayList does not contain a definition for Any...
I am trying to check if an array contains any item from another array. Dont know why but cant post my code. Hope you know what the problem is.

Don't use ArrayList. Use List instead.
Becouse ArrayList doesn't implement IEnumerable<T> generic interface and extension methonds from System.Linq work only with collecions that implement interface IEnumerable<T> like List<T> for example.

ArrayList is a loosely-typed collection (see in reference source) and cannot be used with Enumerable.Any which requires a strongly-typed collection (see in reference source).
BTW, you should not use loosely-typed collections, use generic collections instead.

You shouldn't use non-generic collections.
But If you really want to do this, you can write a helper method for translating your collection to IEnumerable.
static void Main(string[] args)
{
var list = new ArrayList {3, "test", null};
var result = AsEnumerable(list).Any(x => x == null);
}
private static IEnumerable<object> ToEnumerable(ArrayList data)
{
var enumerator = data.GetEnumerator();
while (enumerator.MoveNext())
yield return enumerator.Current;
}
But It's just an example. Use List instead of ArrayList

Related

C# Interface IEnumerable Any() without specifying generic types

I have casted
var info = property.Info;
object data = info.GetValue(obj);
...
var enumerable = (IEnumerable)data;
if (enumerable.Any()) ///Does not compile
{
}
if (enumerable.GetEnumerator().Current != null) // Run time error
{
}
and I would like to see if this enumerable has any elements, via using Linq Query Any(). But unfortunately, even with using Linq, I can't.
How would I do this without specifying the generic type.
While you can't do this directly, you could do it via Cast:
if (enumerable.Cast<object>().Any())
That should always work, as any IEnumerable can be wrapped as an IEnumerable<object>. It will end up boxing the first element if it's actually an IEnumerable<int> or similar, but it should work fine. Unlike most LINQ methods, Cast and OfType target IEnumerable rather than IEnumerable<T>.
You could write your own subset of extension methods like the LINQ ones but operating on the non-generic IEnumerable type if you wanted to, of course. Implementing LINQ to Objects isn't terribly hard - you could use my Edulinq project as a starting point, for example.
There are cases where you could implement Any(IEnumerable) slightly more efficiently than using Cast - for example, taking a shortcut if the target implements the non-generic ICollection interface. At that point, you wouldn't need to create an iterator or take the first element. In most cases that won't make much performance difference, but it's the kind of thing you could do if you were optimizing.
One method is to use foreach, as noted in IEnumerable "Remarks". It also provides details on the additional methods off of the result of GetEnumerator.
bool hasAny = false;
foreach (object i in (IEnumerable)(new int[1] /* IEnumerable of any type */)) {
hasAny = true;
break;
}
(Which is itself easily transferable to an Extension method.)
Your attempt to use GetEnumerator().Current tried to get the current value of an enumerator that had not yet been moved to the first position yet. It would also have given the wrong result if the first item existed or was null. What you could have done (and what the Any() in Enumerable does) is see if it was possible to move to that first item or not; i.e. is there a first item to move to:
internal static class UntypedLinq
{
public static bool Any(this IEnumerable source)
{
if (source == null) throw new ArgumentNullException(nameof(source));
IEnumerator ator = source.GetEnumerator();
// Unfortunately unlike IEnumerator<T>, IEnumerator does not implement
// IDisposable. (A design flaw fixed when IEnumerator<T> was added).
// We need to test whether disposal is required or not.
if (ator is IDisposable disp)
{
using(disp)
{
return ator.MoveNext();
}
}
return ator.MoveNext();
}
// Not completely necessary. Causes any typed enumerables to be handled by the existing Any
// in Linq via a short method that will be inlined.
public static bool Any<T>(this IEnumerable<T> source) => Enumerable.Any(source);
}

What's the Best Way to Add One Item to an IEnumerable<T>?

Here's how I would add one item to an IEnumerable object:
//Some IEnumerable<T> object
IEnumerable<string> arr = new string[] { "ABC", "DEF", "GHI" };
//Add one item
arr = arr.Concat(new string[] { "JKL" });
This is awkward. I don't see a method called something like ConcatSingle() however.
Is there a cleaner way to add a single item to an IEnumerable object?
Nope, that's about as concise as you'll get using built-in language/framework features.
You could always create an extension method if you prefer:
arr = arr.Append("JKL");
// or
arr = arr.Append("123", "456");
// or
arr = arr.Append("MNO", "PQR", "STU", "VWY", "etc", "...");
// ...
public static class EnumerableExtensions
{
public static IEnumerable<T> Append<T>(
this IEnumerable<T> source, params T[] tail)
{
return source.Concat(tail);
}
}
IEnumerable is immutable collection, it means you cannot add, or remove item. Instead, you have to create a new collection for this, simply to convert to list to add:
var newCollection = arr.ToList();
newCollection.Add("JKL"); //is your new collection with the item added
Write an extension method ConcatSingle :)
public static IEnumerable<T> ConcatSingle<T>(this IEnumerable<T> source, T item)
{
return source.Concat(new [] { item } );
}
But you need to be more careful with your terminology.
You can't add an item to an IEnumerable<T>. Concat creates a new instance.
Example:
var items = Enumerable.Range<int>(1, 10)
Console.WriteLine(items.Count()); // 10
var original= items;
items = items.ConcatSingle(11);
Console.WriteLine(original.Count()); // 10
Console.WriteLine(items.Count()); // 11
As you can see, the original enumeration - which we saved in original didn't change.
Since IEnumerable is read-only, you need to convert to list.
var new_one = arr.ToList().Add("JKL");
Or you can get a extension method like;
public static IEnumerable<T> Append<T>(this IEnumerable<T> source, params T[] item)
{
return source.Concat(item);
}
Append() - is exactly what you need, it has been added to the .NET Standard (in 2017), so you no longer need to write your own extension methods. You can simply do this:
arr = arr.Append("JKL");
Since .NET is open source, here you can look on the implementation (it is more sophisticated than custom methods suggested above):
https://github.com/dotnet/runtime/blob/master/src/libraries/System.Linq/src/System/Linq/AppendPrepend.cs
You're assigning an array to an IEnumerable. Why don't you use the Array type instead of IEnumerable?
Otherwise you can use IList (or List) if you want to change the collection.
I use IEnumerable only for methods params when I need to read and IList (or List) when I need to change items in it.

How to get an empty list of a collection?

I have a collection of anonymous class and I want to return an empty list of it.
What is the best readable expression to use?
I though of the following but I don't think they are readably enough:
var result = MyCollection.Take(0).ToList();
var result = MyCollection.Where(p => false).ToList();
Note: I don't want to empty the collection itself.
Any suggestion!
Whats about:
Enumerable.Empty<T>();
This returns an empty enumerable which is of type T. If you really want a List so you are free to do this:
Enumerable.Empty<T>().ToList<T>();
Actually, if you use a generic extension you don't even have to use any Linq to achieve this, you already have the anonymous type exposed through T
public static IList<T> GetEmptyList<T>(this IEnumerable<T> source)
{
return new List<T>();
}
var emp = MyCollection.GetEmptyList();
Given that your first suggestion works and should perform well - if readability is the only issue, why not create an extension method:
public static IList<T> CreateEmptyCopy(this IEnumerable<T> source)
{
return source.Take(0).ToList();
}
Now you can refactor your example to
var result = MyCollection.CreateEmptyCopy();
For performance reasons, you should stick with the first option you came up with.
The other one would iterate over the entire collection before returning an empty list.
Because the anonymous type there is no way, in source code, to create a list. There is, however, a way to create such list through reflection.

C# convert reflection.propertyinfo to Generic.List<>

How do I go about converting a reflection.propertyinfo[] to a generic.list<>?
One of the List<T> constructors accepts an IEnumerable<T> as its argument (i.e., your PropertyInfo array):
var list = new List<PropertyInfo>( propInfoArray );
var list = yourArray.ToList();
Try using .ToList()
http://msdn.microsoft.com/en-us/library/bb342261.aspx
All of the above are correct. But it should also be mentioned that, like List<T> all .net arrays implement IList<T>.
var IList<PropertyInfo> ilist = reflection.propertyinfo;
Since I know that, almost all my functions accept IList<T> when I need a list-like collection, which I can use with traditional arrays and lists.
Use the extension method ToList() available in the System.Linq namespace:
var myProperties = propertyInfoArray.ToList();

What is the best way to cast from ArrayList to List in .Net 2.0

I have a ArrayList of type BookingData to List<BookingData> ?
I am using .net 2.0 so i cannot use arrayList.Cast<int>().ToList() , and I dont want to make here foreach loop , do you have better ideas ?
Thanks.
Do note that something is going to have to enumerate the array-list to construct the List<T>; its only a matter of whether you do it yourself or leave it to some other (framework / utility) method.
If this is a one-off, the solution that you wish to avoid (using an "in-place" foreach loop to do the conversion) is a perfectly reasonable option. If you find yourself doing this quite often, you could extract that out into a generic utility method, as in cdhowie's answer.
If your restriction is only that you must target .NET 2.0 (but can use C# 3), consider LINQBridge, which is a reimplementation of LINQ to Objects for .NET 2.0. This will let you use the Cast sample you've provided without change. It will work on C# 2 too, but you won't get the benefits of the extension-method syntax, better type-inference etc.
If you don't care about performance, nor do you want to go to the trouble of writing a utility method, you could use the in-built ArrayList.ToArray method to help out, by creating an intermediary array that plays well with List<T> (this isn't all that shorter than a foreach):
ArrayList arrayList = ...
// Create intermediary array
BookingData[] array = (BookingData[]) arrayList.ToArray(typeof(BookingData));
// Create the List<T> using the constructor that takes an IEnumerable<T>
List<BookingData> list = new List<BookingData>(array);
Finally, I would suggest, if possible to abandon using the obsolete non-generic collection-classes altogether.
Let's keep it simple:
// untested
List<T> ConvertArrayList<T>(ArrayList data)
{
List<T> result = new List<T> (data.Count);
foreach (T item in data)
result.Add(item);
return result;
}
...
List<BookingData> newList = ConvertArrayList<BookingData>(oldList);
Use this method:
public static List<T> ConvertToList<T>(ArrayList list)
{
if (list == null)
throw new ArgumentNullException("list");
List<T> newList = new List<T>(list.Count);
foreach (object obj in list)
newList.Add((T)obj);
// If you really don't want to use foreach:
// for (int i = 0; i < list.Count; i++)
// newList.Add((T)list[i]);
return newList;
}
Then you can:
List<BookingData> someList = ConvertToList<BookingData>(someArrayList);
You have to use foreach:
foreach (Object item in list1)
{
list2.Add((BookingData)item);
}
ToList() method is nothing but the Synthetic sugar for creating a List representation but internally it is also using loop to generate the list item.
so it is much cleaner and simpler to use a foreach iterator block.

Categories

Resources