C# - Convert Object to Array to get Data by Index - c#

I have a webservice that returns me an object with data
object data = _wsUsuario.CarregarDadosUsuario(_view.Usuario);
This object, called data, returns me the following:
[0] 84
[1] Marcelo Camargo
[2] myemail#myprovider.com
[3] 2
If I try to do
MessageBox.Show(data[0]);
Then the compiler says me:
Cannot apply indexing to an expression of type 'object'. I searched and wonder if there is a way to convert this object of strings and integers to an array. Can you give me a hand?

Assuming the data is an array of strings, then you would need to cast it accordingly:
object[] oData = (data as object[]) ?? new object[0];
This will TRY to cast to object[] but if it isn't castable, it will return null and the null coalescing operator ?? will return an empty object array instead.

An object doesn't have an indexer. An array does.
I think you downcasted the functions return type from a specific strong type object(some kind of array) into a basic 'object'.
What should happen:
// res should be an array
CarregarDadosUsuarioReturnType res = _wsUsuario.CarregarDadosUsuario(_view.Usuario);
MessageBox.Show(res[0]);
If, for any reason this service implicitly recieves an object simply cast this into:
object data = _wsUsuario.CarregarDadosUsuario(_view.Usuario);
var arr = data as ArrType[]; // where ArrType = the array type.
MessageBox.Show(arr[0]);

Related

how to transform array of c# primitive type assigned to Object into something I can iterate through?

I'm attempting to iterate through the fields in an Object (using reflection, via FieldInfo) and dump their values... and just fell headfirst into a C# vs Java trap.
The problem I'm running into is the fact that
FieldInfo.GetValue(srcObject) can return an int[] (or some other array of primitive values) as an Object
c# doesn't allow you to cast an Object holding an int[] to Object[]
So... if
System.Object val = fieldInfo.GetValue(srcObject)
and
val.GetType().IsArray returns 'True'
... what do I need to do to
Recognize at runtime that 'val' is "an Object that's an array, but not an array of Objects"?
transform 'val' into an array of printable values that I can iterate through?
You can cast it to System.Collections.IEnumerable first, because all arrays are enumerable:
Foo f = new Foo();
var fieldInfo = typeof(Foo).GetField("field");
var value = fieldInfo.GetValue(f);
if (value.GetType().IsArray) {
var enumerable = (IEnumerable)value;
foreach (var item in enumerable) {
Console.WriteLine(item);
}
}
If you have multi-dimensional arrays and you want to get the length of each dimension, then you can cast to Array:
if (value.GetType().IsArray) {
var array = (Array)value;
Then you can call GetLength:
int firstDimensionLength = array.GetLength(0);
int secondDimensionLength = array.GetLength(1);

Why can't I convert an object (which is really object[]) to string[]?

I have a field that is of type 'object'. When I inspect it within the Watch window of visual studio I see its Object[] and when I drill into the elements I see each element is a string.
But when I try to cast this to a String[] I get this error:
Cannot cast 'MyObject' (which has an actual type of 'object[]') to 'string[]' string[]
Any reason why I can't do this cast? What is the best way to convert this object to a string array?
This is a particularly confusing feature of C#. Here's the deal.
Throughout this discussion we assume that the element type of an array is a reference type, not a value type.
C# supports unsafe array covariance. That means that if you have an array of string, you can convert it to an array of object, because a string can be converted to an object:
string[] a1 = { "hello", "goodbye" };
object[] a2 = a1; // Legal
If you then try to get an element out of a2, it works:
object o3 = a2[0];
That's legal because a2[0] is really a1[0], which is a string, which is convertible to object.
However, if you attempt to write to the array then you'll get an error at runtime:
a2[0] = new object();
This fails at runtime because a2 is really an array of strings, and you can't put a non-string into an array of strings.
So C# is already horribly broken; it is possible to write a program that compiles and looks normal but suddenly crashes with a type exception at runtime because you tried to put an object into an array of objects that is not actually an array of objects.
The feature you want is even more broken than that, and thank goodness C# does not support it. The feature you want is:
object[] a4 = { "Hello" };
string[] a5 = a4;
That would be unsafe array contravariance. It breaks horribly like this:
a4[0] = new Customer(); // Perfectly legal
string s6 = a5[0];
And now we just copied a Customer into a variable of type string.
You should avoid any kind of array covariance or contravariance; array contravariance is, as you've discovered, not legal, and array covariance is making little time bombs in your program that go off unexpectedly. Make your arrays of the right type to begin with.
string[] newarr = Array.ConvertAll(objects, s => (string)s);
--EDIT--
since you've said I have an object (knowing that it is an object[] actually)
string[] newarr = Array.ConvertAll((object[])objects, s => (string)s);
object[] original = new object[]{"1", "2"};
//some code in between here
object obj = original ;
object[] objArray = (object[])obj;
string[] newArray = new string[objArray.Length];
for(int i = 0; i < newArray; i++)
{
newArray[i] = (string)objArray[i];
}
Other answers here are showing you quicker/shorter ways of doing the conversion. I wrote the whole thing out like this because it shows what's really going on and what needs to happen. You should use one of the simpler methods in your actual production code.
The rule in object oriented programming is -
"Derived class can always be type casted to base class" AND
"A Base class can be casted to derived class only if the current instance that base class hold off is actually derived class"
e.g. (A is base and B is derived)
A a = new B(); // legal;
B b = (B) a ; // legal as "a" is actually B (in first statement)
illegal : >
A a = new A();
B b = (B) a; // not legal as "a" is A only.
Same thing is applied to Object and String classes. Object is base class and string is Derived class.
You can convert the real string[] to object[].
This is a Array covariance
Can find a clear example in link.
You should cast each element in the collection and not the collection itself.
object[] ovalues = new object[] { "alpha", "beta" };
string[] svalues = ovalues.Cast<string>().ToArray();

C#: Generic list of enum values

Is there a way to create a method that gets an enum type as a parameter, and returns a generic list of the enum underlying type from it's values, no matter if the underlying type is int\short byte etc'...
I saw this answer of Jon Skeet, but it looks way too complicated.
If you want to pass in a Type, it can't really be usefully generic - you'd have to return a single type that isn't directly related to the input, hence something like:
public static Array GetUnderlyingEnumValues(Type type)
{
Array values = Enum.GetValues(type);
Type underlyingType = Enum.GetUnderlyingType(type);
Array arr = Array.CreateInstance(underlyingType, values.Length);
for (int i = 0; i < values.Length; i++)
{
arr.SetValue(values.GetValue(i), i);
}
return arr;
}
This is a strongly-typed vector underneath, so you could cast that to int[] etc.
While Marc's answer isn't wrong its somewhat unnecessary.
Enum.GetValues(type) returns a TEnum[] so this method is kind of unnecessary as if you know the underlying type you can just cast TEnum[] to its underlying type array.
var underlyingArray = (int[])Enum.GetValues(typeof(StringComparison));
is valid C# that will compile and won't throw an exception at runtime. Since you wanted a list once you have the array you can pass it to the List<Tunderlying> constructor or you can just call the ToArray() extension method.
Edit: you could write the function as such::
public static TUnderlying[] GetValuesAs<TUnderlying>(type enumType)
{
return Enum.GetValues(enumType) as TUnderlying[];
}
But then you would have to know the underlying type first.

.NET Reflection and an array

I'm trying to get the value of a property that is a single dimensional array via reflection
I tried something like this: (try catches removed for clarity)
string[] fieldOrder;
PropertyInfo fieldOrderColumn;
fieldOrderColumn = targetType.GetProperty("OrderArray");
if (fieldOrderColumn == null)
throw new Exception(targetType.Name + " the OrderArray is null ");
fieldOrder = (string[])fieldOrderColumn.GetValue(targetType, null); //what should I use insted of this?
Clearly the last line is wrong, and is trying to get a non array object, I assumed a
quick google and I'd be on my way, but I'm unable to find it. I don't know the lenght of the array at run time.
Any hints or links or help would be greatly appreciated.
You need to pass an instance of the type into GetValue. If it is a static property, pass null. Currently you are passing the type. I would expect to see (roughly):
Type targetType = obj.GetType();
...[snip]
fieldOrder = (string[])fieldOrderColumn.GetValue(obj, null);
Note that if you aren't sure of the type of array, you can just use Array (instead of string[]), or for single-dimension arrays IList may be useful (and will handle arrays, lists etc):
IList list = (IList)fieldOrderColumn.GetValue(obj, null);

How to convert a JavaScript array of doubles to a .NET array of doubles?

What is the best way to convert a JavaScript array of doubles
return [2.145, 1.111, 7.893];
into a .NET array of doubles, when the Javascript array is returned from a webbrowser controls document object
object o = Document.InvokeScript("getMapPanelRegion");
without using strings and parsing?
The object returned is of type __ComObject as it is an array being returned. The array will be a fixed size as I am using this to return three values back to the calling code. My current solution is to return a | deliminated string of the three value, I then split and parse the string to get my three doubles. If possible I would like to not have to use the string manipulation as this feels like a hack.
From MSDN (HtmlDocument.InvokeScript Method):
The underlying type of the object returned by InvokeScript will vary. If the called Active Scripting function returns scalar data, such as a string or an integer, it will be returned as a string ...
It seems that integers will be returned as string, you could asume that the same applies to doubles.
EDIT:
I forgot that you were talking about an array. Anyhow, MSDN continues:
... If it returns a script-based object, such as an object created using JScript or VBScript's new operator, it will be of type Object ...
So it seems that you will get an object instead, but that doesn't help the fact that you will have to convert it inside your C# code.
EDIT 2:
As for the conversion of the actual ComObject. After reading this which is about Excel, but it still returns a ComObject, it seems that your current aproach with the string seems like the simpler one. Sometimes a hack is the best solution :D
This "problem" amounts to transforming VARIANT into an C# array. For this probably the easiest way is to use reflection. Here is how:
private static IEnumerable<object> SafeArrayToEnmrble (object comObject)
{
Type comObjectType = comObject.GetType();
// spot here what is the type required
if (comObjectType != typeof(object[,]))
// return empty array, throw exception or whatever is your fancy
return new object[0];
int count = (int)comObjectType.InvokeMember("Length", BindingFlags.GetProperty, null, comObject, null);
var result = new List<object>(count);
var indexArgs = new object[2];
for (int i = 1; i <= count; i++)
{
indexArgs[0] = i;
indexArgs[1] = 1;
object valueAtIndex = comObjectType.InvokeMember("GetValue", BindingFlags.InvokeMethod, null, comObject, indexArgs);
result.Add(valueAtIndex);
}
return result;
}

Categories

Resources