How to add to object[] in loop? - c#

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

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 convert a genericlist to an object array -> object[]

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

Literal notation for Dictionary in C#?

I currently have a WebSocket between JavaScript and a server programmed in C#. In JavaScript, I can pass data easily using an associative array:
var data = {'test': 'val',
'test2': 'val2'};
To represent this data object on the server side, I use a Dictionary<string, string>, but this is more 'typing-expensive' than in JavaScript:
Dictionary<string, string> data = new Dictionary<string,string>();
data.Add("test", "val");
data.Add("test2", "val2");
Is there some kind of literal notation for associative arrays / Dictionarys in C#?
You use the collection initializer syntax, but you still need to make a new Dictionary<string, string> object first as the shortcut syntax is translated to a bunch of Add() calls (like your code):
var data = new Dictionary<string, string>
{
{ "test", "val" },
{ "test2", "val2" }
};
In C# 6, you now have the option of using a more intuitive syntax with Dictionary as well as any other type that supports indexers. The above statement can be rewritten as:
var data = new Dictionary<string, string>
{
["test"] = "val",
["test2"] = "val2"
};
Unlike collection initializers, this invokes the indexer setter under the hood, rather than an appropriate Add() method.
While, the dictionary initializer answer is totally correct, there is another approach to this that I would point out (but I might not recommend it). If your goal is to provide terse API usage, you could use anonymous objects.
var data = new { test1 = "val", test2 = "val2"};
The "data" variable is then of an "unspeakable" anonymous type, so you could only pass this around as System.Object. You could then write code that can transform an anonymous object into a dictionary. Such code would rely on reflection, which would potentially be slow. However, you could use System.Reflection.Emit, or System.Linq.Expressions to compile and cache a delegate that would make subsequent calls much faster.
Asp.net MVC APIs use this technique in a number of places that I've seen. A lot of the Html Helpers have overloads that accept either an object or a dictionary. I assume the goal of their API design is the same as what you are after; terse syntax at the method call.
Use Dictionary Literals (C#9 proposal) [rejected] or the new syntax (beginning with C#9)
C#9 introduces a simpler syntax to create initialized Dictionary<TKey,TValue> objects without having to specify either the Dictionary type name or the type parameters. The type parameters for the dictionary are inferred using the existing rules used for array type inference.
// C# 1..8
var x = new Dictionary <string,int> () { { "foo", 4 }, { "bar", 5 }};
// C# 9
var x = ["foo":4, "bar": 5];
This synthax makes the work with dictionaries in C# simpler and removing the redundant code.
You can follow the issue on GitHub (and here is the milestone for C#9).
Edit: This proposal is currently rejected:
[...] We think there are a number of interesting use cases around initializing data, particularly for things like immutable dictionaries. We don't find the existing syntax for initializing a dictionary that onerous, nor do we see it as a frequent pattern in code that would benefit much from a language feature. We thing that the general area of initializing data should be looked at again after we do records and withers. [...]
current milestone:
Note that beginning with C# 9.0, constructor invocation expressions are target-typed. That is, if a target type of an expression is known, you can omit a type name, as the following example shows:
Dictionary<int, List<int>> lookup = new()
{
[1] = new() {1, 2, 3},
[2] = new() {5, 8, 3},
[5] = new() {1, 0, 4}
};
As the preceding example shows, you always use parentheses in a target-typed new expression.
If a target type of a new expression is unknown (for example, when you use the var keyword), you must specify a type name.
MSDN
Using DynamicObject, it is not that difficult to create a simpler dictionary initializer.
Imagine you want to call the following method
void PrintDict(IDictionary<string, object> dict) {
foreach(var kv in dict) {
Console.WriteLine (" -> " + kv.Key + " = " + kv.Value);
}
}
using a literal syntax like
var dict = Dict (Hello: "World", IAm: "a dictionary");
PrintDict (dict);
This can be accomplished by creating a dynamic object like this
dynamic Dict {
get {
return new DynamicDictFactory ();
}
}
private class DynamicDictFactory : DynamicObject
{
public override bool TryInvoke (InvokeBinder binder, object[] args, out object result)
{
var res = new Dictionary<string, object> ();
var names = binder.CallInfo.ArgumentNames;
for (var i = 0; i < args.Length; i++) {
var argName = names [i];
if(string.IsNullOrEmpty(argName)) throw new ArgumentException();
res [argName] = args [i];
}
result = res;
return true;
}
}

How to replace value in string array

How to remove my value in String Array and how i can rearrange
public string[] selNames = new string[5];
selNames[0]="AA";
selNames[1]="BB";
selNames[2]="CC";
selNames[3]="DD";
selNames[4]="EE";
In certain Conditaion i need to Check for the existing value and i want to remove it from my collection, How i can do it.
i tried like below, but i cannot, it returns true, but how to make that index value to null
If(selNames .Contains("CC").ToString()==true)
{
// how to make that index null which contains the "CC"; and i need to rearrage the array
}
You can do following.
var newArray = selNames.Where(s => s != "CC").ToArray();
where s is the arg of the Func<TSource, bool> delegate TSource is string in your case.
So it will compare each string in array and return all which is not "СС"
here is a link to msdn
You can use the 'List< T >' for checking the existing values and also can remove the item from the list and also can arrange the list.
The following is the code snippet:
List<string> list = new List<string>();
list.Add("AA");
list.Add("BB");
list.Add("CC");
list.Add("DD");
list.Add("EE");
list.Add("FF");
list.Add("GG");
list.Add("HH");
list.Add("II");
MessageBox.Show(list.Count.ToString());
list.Remove("CC");
MessageBox.Show(list.Count.ToString());

Categories