Convert generic ienumerable to arraylist - c#

I need to convert the linq query from generic ienumerable to arraylist.
ArrayList myArrayList = new ArrayList();
var b =
(from myObj in myCollection
select new myClass
{
Name = myObj.Name,
ac = myObj.ac
});
I have tried doing
b.Cast<ArrayList>();
but it is not working.
Edited :
I got it working with #devdigital solution
but i will also want to point out that at same time i found a hackish solution.
myArrayList.InsertRange(0, b.ToArray());

One of the constructors for the ArrayList type takes an ICollection, so you should be able to do the following:
var b =
(from myObj in myCollection
select new myClass
{
Name = myObj.Name,
ac = myObj.ac
}).ToArray();
ArrayList myArrayList = new ArrayList(b);

I'd suggest you to use a List<T> rather than an ArrayList. You can actually use the ToList extension method or the List's constructor which takes an IEnumerable<T>:
var myList = b.ToList(); // either
var myListTwo = new List<myClass>(b); // or
List<T> was newly introduced with .NET 2.0 and is generic. This means it yields you values of your actual type at compile-time, which is myClass, instead of object.
Edit: If you actually need an ArrayList, you need to copy b twice, as it cannot deal with IEnumerable directly, as devdigital pointed out in his reply:
ArrayList arrayList = new ArrayList(b.ToArray());

You can convert your IEnumerable to an array with ToArray(), then construct an ArrayList from that array.
var b = (from myObj in myCollection
select new myClass
{
Name = myObj.Name,
ac = myObj.ac
});
var myArrayList = new ArrayList(b.ToArray());

ArrayList arrayList = new ArrayList(b.ToList());

Related

How to create a list that contains a list of different types

Let's say I have such lists :
var firstList = new List<ofsometype>();
var secondList = new List<ofsomeanothertype>();
var thirdList = new List<anothertype>();
How can I make a list that accepts those lists? Like
var mainList = new List<???>();
mainList.Add(firstlist);
mainList.Add(secondlist);
mainList.Add(thirdlist);
Thanks.
I'd probably use a Dictionary collection instead :
var firstList = new List<ofsometype>();
var secondList = new List<ofsomeanothertype>();
var thirdlist = new List<anothertype>();
var listsDict = new Dictionary<Type, object>();
listsDict.Add(typeof(ofsometype), firstlist);
listsDict.Add(typeof(ofsomeanothertype), secondlist);
listsDict.Add(typeof(anothertype), thirdlist);
The advantage here is that it gives you the information regarding the type of a list. This could be used for two things :
Filter list for a certain type only
Know the type forList<object> later by simply using the key
P.S.
Depending on what the solution is and what you'd need to achieve you can use generics (if type is known) or dynamics - if type is unknown, but still a dynamic operation at run-time is required if compiler doesn't know the type.
If you want to add items from lists of different types, then they need to share either a common base class, or inherit from the same interface, e.g.
ofsometype : ISomeInterface
ofsomeanothertype: ISomeInterface
anothertype: ISomeInterface
var firstList = new List<ofsometype>();
var secondList = new List<ofsomeanothertype>();
var secondList = new List<anothertype>();
var mainList = new List<ISomeInterface>();
mainList.AddRange(firstlist);
mainList.AddRange(secondlist);
mainList.AddRange(thirdlist);
You'll be limited to accessing the members exposed by ISomeInterface when retrieving items from the list, unless you resort to casting/reflection.
This can also be achieved by adding them to a List<object>, but that gives you next to no information about what's contained in the list.
Simply use Object.
List<Object> or Object[] for array
var mainList = new List<List<Object>>();
mainList.Add(firstlist);
mainList.Add(secondlist);
mainList.Add(thirdlist);
I suggest this
var mainList = new List<Object[]>();
mainList.Add(firstlist.toArray());
mainList.Add(secondlist.toArray());
mainList.Add(thirdlist.toArray());

why can't I assign a list of an object to an IList of the interface it implements [duplicate]

It seems that a List object cannot be stored in a List variable in C#, and can't even be explicitly cast that way.
List<string> sl = new List<string>();
List<object> ol;
ol = sl;
results in Cannot implicitly convert type System.Collections.Generic.List<string> to System.Collections.Generic.List<object>
And then...
List<string> sl = new List<string>();
List<object> ol;
ol = (List<object>)sl;
results in Cannot convert type System.Collections.Generic.List<string> to System.Collections.Generic.List<object>
Of course, you can do it by pulling everything out of the string list and putting it back in one at a time, but it is a rather convoluted solution.
Think of it this way, if you were to do such a cast, and then add an object of type Foo to the list, the list of strings is no longer consistent. If you were to iterate the first reference, you would get a class cast exception because once you hit the Foo instance, the Foo could not be converted to string!
As a side note, I think it would be more significant whether or not you can do the reverse cast:
List<object> ol = new List<object>();
List<string> sl;
sl = (List<string>)ol;
I haven't used C# in a while, so I don't know if that is legal, but that sort of cast is actually (potentially) useful. In this case, you are going from a more general class (object) to a more specific class (string) that extends from the general one. In this way, if you add to the list of strings, you are not violating the list of objects.
Does anybody know or can test if such a cast is legal in C#?
If you're using .NET 3.5 have a look at the Enumerable.Cast method. It's an extension method so you can call it directly on the List.
List<string> sl = new List<string>();
IEnumerable<object> ol;
ol = sl.Cast<object>();
It's not exactly what you asked for but should do the trick.
Edit: As noted by Zooba, you can then call ol.ToList() to get a List
You cannot cast between generic types with different type parameters. Specialized generic types don't form part of the same inheritance tree and so are unrelated types.
To do this pre-NET 3.5:
List<string> sl = new List<string>();
// Add strings to sl
List<object> ol = new List<object>();
foreach(string s in sl)
{
ol.Add((object)s); // The cast is performed implicitly even if omitted
}
Using Linq:
var sl = new List<string>();
// Add strings to sl
var ol = new List<object>(sl.Cast<object>());
// OR
var ol = sl.Cast<object>().ToList();
// OR (note that the cast to object here is required)
var ol = sl.Select(s => (object)s).ToList();
The reason is that a generic class like List<> is, for most purposes, treated externally as a normal class. e.g. when you say List<string>() the compiler says ListString() (which contains strings). [Technical folk: this is an extremely plain-English-ified version of what's going on]
Consequently, obviously the compiler can't be smart enough to convert a ListString to a ListObject by casting the items of its internal collection.
That's why there's extension methods for IEnumerable like Convert() that allow you to easily supply conversion for the items stored inside a collection, which could be as simple as casting from one to another.
This has a lot to do with covariance, e.g., generic types are considered as parameters, and if the parameters do not resolve properly to a more specific type then the operation fails. The implication of such is that you really cannot cast to a more general type like object. And as stated by Rex, the List object won't convert each object for you.
You might want to try the ff code instead:
List<string> sl = new List<string>();
//populate sl
List<object> ol = new List<object>(sl);
or:
List<object> ol = new List<object>();
ol.AddRange(sl);
ol will (theoretically) copy all the contents of sl without problems.
Yes, you can, from .NET 3.5:
List<string> sl = new List<string>();
List<object> ol = sl.Cast<object>().ToList();
Mike - I believe contravariance isn't allowed in C# either
See Generic type parameter variance in the CLR for some more info.
I think that this (contravariance) will actually be supported in C# 4.0.
http://blogs.msdn.com/charlie/archive/2008/10/27/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx
That's actually so that you don't try to put any odd "object" in your "ol" list variant (as List<object> would seem to allow) - because your code would crash then (because the list really is List<string> and will only accept String type objects). That's why you can't cast your variable to a more general specification.
On Java it's the other way around, you don't have generics, and instead everything is List of object at runtime, and you really can stuff any strange object in your supposedly-strictly typed List. Search for "Reified generics" to see a wider discussion of java's problem...
Such covariance on generics is not supported, but you can actually do this with arrays:
object[] a = new string[] {"spam", "eggs"};
C# performs runtime checks to prevent you from putting, say, an int into a.
Here is another pre-.NET 3.5 solution for any IList whose contents can be cast implicitly.
public IList<B> ConvertIList<D, B>(IList<D> list) where D : B
{
List<B> newList = new List<B>();
foreach (D item in list)
{
newList.Add(item);
}
return newList;
}
(Based on Zooba's example)
I have a:
private List<Leerling> Leerlingen = new List<Leerling>();
And I was going to fill it with data collected in an List<object>
What finally worked for me was this one:
Leerlingen = (List<Leerling>)_DeserialiseerLeerlingen._TeSerialiserenObjecten.Cast<Leerling>();
.Cast it to the type you want to get an IEnumerable from that type, then typecast the IEnemuerable to the List<> you want.
Mm, thanks to previous comments I found two ways to find it out. The first one is getting the string list of elements and then casting it to IEnumerable object list:
IEnumerable<object> ob;
List<string> st = new List<string>();
ob = st.Cast<object>();
And the second one is avoiding the IEnumerable object type, just casting the string to object type and then using the function "toList()" in the same sentence:
List<string> st = new List<string>();
List<object> ob = st.Cast<object>().ToList();
I like more the second way. I hope this helps.
List<string> sl = new List<string>();
List<object> ol;
ol = new List<object>(sl);

Convert 'ArrayList' to 'List<string>' (or 'List<T>') using LINQ

I want to convert an ArrayList to a List<string> using LINQ. I tried ToList() but that approach is not working:
ArrayList resultsObjects = new ArrayList();
List<string> results = resultsObjects.ToList<string>();
Your code actually shows a List<ArrayList> rather than a single ArrayList. If you're really got just one ArrayList, you'd probably want:
ArrayList resultObjects = ...;
List<string> results = resultObjects.Cast<string>()
.ToList();
The Cast call is required because ArrayList is weakly typed - it only implements IEnumerable, not IEnumerable<T>. Almost all the LINQ operators in LINQ to Objects are based on IEnumerable<T>.
That's assuming the values within the ArrayList really are strings. If they're not, you'll need to give us more information about how you want each item to be converted to a string.
I assume your first line was meant to be ArrayList resultsObjects = new ArrayList();.
If the objects inside the ArrayList are of a specific type, you can use the Cast<Type> extension method:
List<string> results = resultsObjects.Cast<string>().ToList();
If there are arbitrary objects in ArrayList which you want to convert to strings, you can use this:
List<string> results = resultsObjects.Cast<object>().Select(x => x.ToString())
.ToList();
You can also use LINQ's OfType<> method, depending on whether you want to raise an exception if one of the items in your arrayList is not castable to the desired type. If your arrayList has objects in it that aren't strings, OfType() will ignore them.
var oldSchoolArrayList = new ArrayList() { "Me", "You", 1.37m };
var strings = oldSchoolArrayList.OfType<string>().ToList();
foreach (var s in strings)
Console.WriteLine(s);
Output:
Me
You
You can convert ArrayList elements to object[] array using ArrayList.ToArray() method.
List<ArrayList> resultsObjects = new List<ArrayList>();
resultsObjects.Add(new ArrayList() { 10, "BB", 20 });
resultsObjects.Add(new ArrayList() { "PP", "QQ" });
var list = (from arList in resultsObjects
from sr in arList.ToArray()
where sr is string
select sr.ToString()).ToList();

C# List<List<T>> Sort

How can I sort a list of list?
persons.OrderBy(p => p.rate).ToList();
The list of list (persons) is declared like this:
public class Persons : List<Person> { }
When I'm trying to run the first statement I get an error:
Cannot convert from 'System.Collections.Generic.List' to
'Persons'
Is there a way to do this using LINQ?
Just because it inherits from a list doesn't mean you can use it like one.
Remember for everything else to see it as a list use interfaces (IList<T>). Then methods depending on IEnumerable, IList, ICollection, etc. can see that it's something it can deal with.
Otherwise, whose to say your Add() (As defined by IList) method isn't named AddPerson in your class?
You can achive it with that statement:
var persons = new Persons ();
persons.AddRange(persons.OrderBy(p => p.rate));
If you want to order all persons in all lists and huddle up them into one list:
var persons = new System.Collections.Generic.List<Persons>();
var trio = new Persons() { new Person(7), new Person(3), new Person(8) };
var pair = new Persons() { new Person(1), new Person(2) };
persons.Add(trio);
persons.Add(pair);
var ordered = persons.SelectMany(p => p).OrderBy(p => p.rate).ToList();
http://msdn.microsoft.com/en-us/library/system.linq.enumerable.selectmany.aspx
To achieve a SortBy behavior, you have to follow these three easy steps:
Store the old items (a. by storing the reference to the old list | b. by copying all entries of the old list into a new one)
Create an empty instance of your container class (a. by creating a new object of the needed type | b. by clearing the old list)
Fill your empty list with the entries while ordering them as you desire.
This little extension method should do the Trick:
public static void SortBy<TList, TItem, TOrder>(this TList source,
Func<TItem, TOrder> sortFunc)
where TList : List<TItem>
{
var l = source.ToList();
source.Clear();
source.AddRange(l.OrderBy(sortFunc));
}

In C#, why can't a List<string> object be stored in a List<object> variable

It seems that a List object cannot be stored in a List variable in C#, and can't even be explicitly cast that way.
List<string> sl = new List<string>();
List<object> ol;
ol = sl;
results in Cannot implicitly convert type System.Collections.Generic.List<string> to System.Collections.Generic.List<object>
And then...
List<string> sl = new List<string>();
List<object> ol;
ol = (List<object>)sl;
results in Cannot convert type System.Collections.Generic.List<string> to System.Collections.Generic.List<object>
Of course, you can do it by pulling everything out of the string list and putting it back in one at a time, but it is a rather convoluted solution.
Think of it this way, if you were to do such a cast, and then add an object of type Foo to the list, the list of strings is no longer consistent. If you were to iterate the first reference, you would get a class cast exception because once you hit the Foo instance, the Foo could not be converted to string!
As a side note, I think it would be more significant whether or not you can do the reverse cast:
List<object> ol = new List<object>();
List<string> sl;
sl = (List<string>)ol;
I haven't used C# in a while, so I don't know if that is legal, but that sort of cast is actually (potentially) useful. In this case, you are going from a more general class (object) to a more specific class (string) that extends from the general one. In this way, if you add to the list of strings, you are not violating the list of objects.
Does anybody know or can test if such a cast is legal in C#?
If you're using .NET 3.5 have a look at the Enumerable.Cast method. It's an extension method so you can call it directly on the List.
List<string> sl = new List<string>();
IEnumerable<object> ol;
ol = sl.Cast<object>();
It's not exactly what you asked for but should do the trick.
Edit: As noted by Zooba, you can then call ol.ToList() to get a List
You cannot cast between generic types with different type parameters. Specialized generic types don't form part of the same inheritance tree and so are unrelated types.
To do this pre-NET 3.5:
List<string> sl = new List<string>();
// Add strings to sl
List<object> ol = new List<object>();
foreach(string s in sl)
{
ol.Add((object)s); // The cast is performed implicitly even if omitted
}
Using Linq:
var sl = new List<string>();
// Add strings to sl
var ol = new List<object>(sl.Cast<object>());
// OR
var ol = sl.Cast<object>().ToList();
// OR (note that the cast to object here is required)
var ol = sl.Select(s => (object)s).ToList();
The reason is that a generic class like List<> is, for most purposes, treated externally as a normal class. e.g. when you say List<string>() the compiler says ListString() (which contains strings). [Technical folk: this is an extremely plain-English-ified version of what's going on]
Consequently, obviously the compiler can't be smart enough to convert a ListString to a ListObject by casting the items of its internal collection.
That's why there's extension methods for IEnumerable like Convert() that allow you to easily supply conversion for the items stored inside a collection, which could be as simple as casting from one to another.
This has a lot to do with covariance, e.g., generic types are considered as parameters, and if the parameters do not resolve properly to a more specific type then the operation fails. The implication of such is that you really cannot cast to a more general type like object. And as stated by Rex, the List object won't convert each object for you.
You might want to try the ff code instead:
List<string> sl = new List<string>();
//populate sl
List<object> ol = new List<object>(sl);
or:
List<object> ol = new List<object>();
ol.AddRange(sl);
ol will (theoretically) copy all the contents of sl without problems.
Yes, you can, from .NET 3.5:
List<string> sl = new List<string>();
List<object> ol = sl.Cast<object>().ToList();
Mike - I believe contravariance isn't allowed in C# either
See Generic type parameter variance in the CLR for some more info.
I think that this (contravariance) will actually be supported in C# 4.0.
http://blogs.msdn.com/charlie/archive/2008/10/27/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx
That's actually so that you don't try to put any odd "object" in your "ol" list variant (as List<object> would seem to allow) - because your code would crash then (because the list really is List<string> and will only accept String type objects). That's why you can't cast your variable to a more general specification.
On Java it's the other way around, you don't have generics, and instead everything is List of object at runtime, and you really can stuff any strange object in your supposedly-strictly typed List. Search for "Reified generics" to see a wider discussion of java's problem...
Such covariance on generics is not supported, but you can actually do this with arrays:
object[] a = new string[] {"spam", "eggs"};
C# performs runtime checks to prevent you from putting, say, an int into a.
Here is another pre-.NET 3.5 solution for any IList whose contents can be cast implicitly.
public IList<B> ConvertIList<D, B>(IList<D> list) where D : B
{
List<B> newList = new List<B>();
foreach (D item in list)
{
newList.Add(item);
}
return newList;
}
(Based on Zooba's example)
I have a:
private List<Leerling> Leerlingen = new List<Leerling>();
And I was going to fill it with data collected in an List<object>
What finally worked for me was this one:
Leerlingen = (List<Leerling>)_DeserialiseerLeerlingen._TeSerialiserenObjecten.Cast<Leerling>();
.Cast it to the type you want to get an IEnumerable from that type, then typecast the IEnemuerable to the List<> you want.
Mm, thanks to previous comments I found two ways to find it out. The first one is getting the string list of elements and then casting it to IEnumerable object list:
IEnumerable<object> ob;
List<string> st = new List<string>();
ob = st.Cast<object>();
And the second one is avoiding the IEnumerable object type, just casting the string to object type and then using the function "toList()" in the same sentence:
List<string> st = new List<string>();
List<object> ob = st.Cast<object>().ToList();
I like more the second way. I hope this helps.
List<string> sl = new List<string>();
List<object> ol;
ol = new List<object>(sl);

Categories