how to convert a genericlist to an object array -> object[] - c#

I googled and fined this link, but still not working
Convert List<T> to object[]
I want to convert the list of int to object array. Why? because I want to add the list as object array in Combbox, it's the argument.
The problem is it adds just "one item" Object[] Array in Combobox, while "tempList" contains 4 items of type int.
I like to add the 4 items in the object[] (object array), now it adds as 1 item and just shows Object[] array in the debugger.
When I look in debugger and type :
customers - it shows object[1] and when I type
customers[0] it shows object[4], so in fact 4 items are added, but how can I get these values.???
List<int> tempList= new CustomersRepository().GetAll().Select(a => a.Numero).ToList();
object[] customers = new object[] { tempList.Cast<object>().ToArray() };
ComboBox.Items.AddRange(customers);

What you are doing is currently creating an Array of arrays. So accessing the values would be done by the following :
customers[0][1]
What I suspect you are actually looking for is the following :
object[] customers = tempList.Cast<object>().ToArray();
This will create an Array of object items called customers.

List<int> tempList= ...;
object[] customers = tempList.Cast<Object>().ToArray();

object[] customers = new object[] { tempList.Cast<object>().ToArray() };
Here you create an object[] with one item: another object[] containing the items of tempList.
Just use object[] customers = tempList.Cast<Object>().ToArray() instead of wrapping it in another object[].

Try it this way :
var customers = tempList.Cast<object>().ToArray();
Or also with an explicit cast :
var customers = tempList.Select(t => (object)t).ToArray();
The problem occured because you are using an initializer for building your list.
This syntax :
var arr = new object[] { "a", "b" }
initialize an array with two strings.
So when you are writing
var arr = new object[] { tempList.Cast<object>().ToArray() }
you build an array of one array!

You dont need ToList() if you anyway want to process further and obtain an array later.
Something like this should be more efficient:
var temp = new CustomersRepository().GetAll().Select(a => a.Numero);
object[] customers = temp.Cast<object>().ToArray();
ComboBox.Items.AddRange(customers);
Had temp been a collection of reference types, you need not cast at all, but rely on array covariance. This should work:
var temp = new CustomersRepository().GetAll().Select(a => a.StringProperty);
object[] customers = temp.ToArray(); //no need of Cast<object>
ComboBox.Items.AddRange(customers);
But this doesn't work in your case since array covariance doesnt support for value types.
Another idea is to have an extension method AddRange that accepts any IEnumerable, not just object[]. Something like:
public static void AddRange(this IList list, IEnumerable lstObject)
{
foreach (T t in lstObject)
list.Add(t);
}
Now you can call:
var customers = new CustomersRepository().GetAll().Select(a => a.Numero);
ComboBox.Items.AddRange(customers);
The best of all is to add the Customers as such, and set the DisplayMember or ValueMember properties to your property, like Numero. Since you have the entire objects in combobox you have more info with you. Something like:
ComboBox.DisplayMember = "Numero";
var customers = new CustomersRepository().GetAll();
ComboBox.Items.AddRange(customers); // using the above extension method

Related

How to cast from an object[] stored as object in C#

I have a List<object> stored in a database.
Each list object consists of an object[] consisting of int values.
I can save, view, and retrieve the data. I can view the data in the debugger. But I cannot cast back to int or an array.
foreach (object item in list)
{
if (item.GetType().IsArray)
{
var arr = item as int[];
foreach (var i in arr)
print(i);
}
}
At the if statement, item shows the data in the debugger pictured below but is false, but how do I cast back to object[]?
I have also tried:
var newItem = item as object[];
Edit: This is how I'm initializing the object. I start with an object because I get cast errors if I try wrapping an int[] when I send to the database.
var listValues = new List<object>();
var newArray = new object[10];
newArray[0] = (int)c.Tag;
newArray[1] = (int)c.FPos;
newArray[2] = (int)c.ToL;
listValues.Add(newArray);
A cast is (usually) different from a conversion. Most of the time when you're casting things in C#, you assume those things are already what you say they are, and you're not changing them at all. There is an exception for value types like int that get "boxed" and "unboxed" when you cast them to and from object. However, that exception does not extend to casting an object[] into an int[].
An int[] is not the same thing as an object[], so you can't just cast it as one. Instead, you have to produce a new array (or Collection, or IEnumerable, or whatever) that consists of all of those objects unboxed into ints. One way to do this is to use the Cast<>() extension method from the System.Linq namespace.
int[] arr = ((object[])item).Cast<int>().ToArray();
Or, as a more complete example:
List<object[]> list = new List<object[]> { new object[] { 1, 2 }, new object[] { 3, 4 } };
foreach (object[] item in list)
{
if (item.GetType().IsArray)
{
var arr = item.Cast<int>();
foreach (var i in arr)
{
Console.WriteLine(i);
}
}
}
Update
Based on your updated question, chances are that the real solution to your problem will go way beyond the scope of the original question. I don't know what mechanism you're using to store this and retrieve it from the database, but if you're using something like Entity Framework you probably need to change your model so that its values are strongly typed. In fact, the way you're taking properties off of an object and putting them into the database as an array is a big code smell: most likely your data model should be flattened into a type with named properties.
But to answer the simplest, most basic part of the question: you've got to cast your objects to the type that they actually are before trying to convert them. If you've got a List<object>, then use that:
foreach (List<object> item in list)
{
int[] arr = item.Cast<int>().ToArray();
foreach (var i in arr)
{
Console.WriteLine(i);
}
}
After selecting your items from the DB you don't get a real array. Instead you get a List which cannot simply be cast to an array type. Thus item.GetType().IsArray is also false because it's a List
Try the following:
foreach (object item in list)
{
IEnumerable<object> itemAsObjectEnumerable = (IEnumerable<object>)item;
IEnumerable<int> itemAsIntEnumerable = itemAsObjectEnumerable.Cast<int>();
foreach (var i in itemAsIntEnumerable)
{
print(i);
}
}

c# access elements of list passed as object type

I want to access members of lists passed in as "object" (the function is handling other data types such as arrays as well). Unfortunately, while this works:
List<object> objectlist = new List<object> { "1", "2" };
object res = ((List<object>)((object)objectlist))[0];
this does not:
List<string> strlist = new List<string> { "1", "2" };
res = (string)((List<object>)((object)strlist))[0];
though it DOES work with arrays.
It does not appear to be possible to convert regular lists to List.
Is using reflection (but with GetMethods to avoid repeated string searches):
MethodInfo info = ((object)list).GetType().GetMethod("get_Item");
object s1 = (object)info.Invoke(((object)list), new object[] { 0 });
the only way to do this?
No, a List<string> isn't a List<object>... although it is an IEnumerable<object> due to generic covariance. However, a List<int> isn't even an IEnumerable<object> as covariance doesn't apply to value type type arguments. Fortunately, it is an IEnumerable.
So to get the first element of an arbitrary object which you know implements IEnumerable, I'd just use:
object first = ((IEnumerable) source).Cast<object>().First();
(Due to IEnumerator not implementing IDisposable, more "manual" ways of doing it end up being a bit fiddly.)
List<T> implements non-generic IList. If you only want to retrieve items from the list, you can cast to it. One-dimensional arrays implement it too, so the cast will work for both arrays and lists
res = (string)((IList)((object)strlist))[0];

How to add to object[] in loop?

EDIT: original question did not make sense so hopefully this one does.
How to make the following object below
object[] parms = { "p1", 1, "p2", 2, "p3", 3,..., "pn", n };
Obviously this is not working:
foreach (var id in ids)
{
objects[] parms = { "p" + id.ToString(), id };
}
Since the question has been changed....
You can construct your object array like:
List<int> ids = new List<int> { 1, 2, 3, 4, 5 }; //assuming your ids are like that
List<object> objList = new List<object>();
foreach (var item in ids)
{
objList.Add("p" + item);
objList.Add(item);
}
object[] parms = objList.ToArray();
now parms would contain multiple objects, first a string with "p" + id and the second as id.
Not really sure why you need such construct, you can use Dictionary<int,string> or a List of your custom object with a property for string and another for int id.
Old Answer.
Just call it like:
List<object> parms = new List<object>();
someFunction("somestring", parms.ToArray());
See: params (C# Reference)
You can send a comma-separated list of arguments of the type specified
in the parameter declaration or an array of arguments of the
specified type.
You can also do:
someFunction("string", ids.Select(r => "p" + r).ToArray());
You can simply convert the list to an array.
someFunction("", parms.toArray());
The other answers are correct in their instruction of how to use params.
But in your case, you're double-nesting your object arrays.
Your params[0] is an object[2] - presumably because there were two id in ids, and because you're adding each "thing made out of an ID" as an object[].
So params[0][0] is your first id's pID string, and params[0][1] is its numeric id.
To make this cleaner, you could define your own class to hold the information, or use Tuple<>. Then, inspect the contents of your params[] - which should be of this type, and you can cast them and use them as such.
It is possible to change it like this:
someFunction( string a, IList parms)
{
// this should receive array of actual {p#'s, #'s}
}

Retrieve Data From IEnumerable?

[CrossPost From MSDN]
I had a task that, I need to send a generic List to a method, where I need to iterate it and convert it to an Excel File. I already did this with Data Table, but with Generic list I am facing some problems (I don't want to convert my generic list to Data Table). I will paste the code which helps me out for an answer.
I Had Two Generic Lists
List<User> objList = new List<User>();
List<Student> objStudent = new List<Student>();
// I am adding some Item to List
User obj = new User(1, "aaa");
User obj1 = new User(2, "bbb");
User obj2 = new User(3, "ccc");
User obj3 = new User(4, "ddd");
Student sobj = new Student(1, "aaa");
Student sobj1 = new Student(2, "bbb");
Student sobj2 = new Student(3, "ccc");
Student sobj3 = new Student(4, "ddd");
objList.Add(obj);ExportToExcel(objList);
To Export it to Excel , I am passing the lists to the below methods as
public void ExportToExcel<T>(IEnumerable<T> list)
{
PropertyInfo[] piT = typeof(T).GetProperties();
var Users = list.ToList();
Type myType = (typeof(T));
}
When I am passing my list to Ienumerable... I am not able to retrieve the data present in the List IEnumerable list. If I retrieve the data , then I can handle further. Could any one suggest me the better Idea?
If your always going to work with List<T> you could change IEnumerable<T> to IList<T>. AFAIK the IEnumerable interface does not define methods for accessing the data inside the collection, only to iterate it.
You could even use ICollection<T> if it suits your needs.
If you need to access the values of all the properties on type T, you can use the PropertyInfo.GetValue method:
public void ExportToExcel<T>(IEnumerable<T> items)
{
var properties = typeof(T).GetProperties();
foreach(var item in items)
{
foreach(var property in properties)
{
var value = property.GetValue(item, null);
// Do something else with the property's value
}
}
}
Edit in response to comment
You indicated you might receive a single list or a list of lists. You can add another overload which takes the composed lists, then iterate through it and export each individual list:
public void ExportToExcel<T>(IEnumerable<IEnumerable<T>> itemSets)
{
foreach(var itemSet in itemSets)
{
ExportToExcel(itemSet);
}
}

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));
}

Categories