Casting system.array to object in c# - c#

my function has the following signature
function myfunction(ref object)
I use it as such
Array arr = Array.CreateInstance(System.Type.GetType("System.String"), 2);
arr.SetValue("1", 0);
myfunction( ref arr);
And I am getting
"cannot convert from 'ref System.Array' to 'ref object'"
I was under the impression that System.Array is object ...so why am I getting this error? Is object different from Object?

The problem you're having is that while an array is an object, an object is not an array, so in your function, if your array could be passed in as a ref object, the array could be assigned anything that is an object.
Edit:
To fix this problem declare a ref variable to use in place of the array variable:
Array arr = Array.CreateInstance(System.Type.GetType("System.String"), 2);
arr.SetValue("1", 0);
object referenceObject = arr;
myfunction( ref referenceObject );

Think of 'ref object' as "I take a reference to a variable that can store an Object". Suppose that 'myfunction' tried to store an 'int' to the variable you passed? This would fail at runtime, which is undesirable.
On a side note, you can use typeof(string) in place of calling GetType("System.String"). You can also just say:
Object arr = new string[2];
To access the array first, you can do this:
string[] arr = new string[2];
arr[0] = "1";
object arrObj = arr;
myfunction(ref arrObj);
I would double check that you're using the method myfunction correctly; it's a rather unusual parameter type for taking an initialized array.

Declare the variable as object and not as array.
To populate the array with values you should keep your array variable and declare another one to give it to the method.
Array myArray = ....;
Object myObject = myArray;
myFunction(ref myObject);
// Update the original reference
myArray = myObject as Array;

Related

Convert double[] to System.array c#

I'm using a visual basic library and one of the methods I'm using calls for a System.Array to be passed into it.
I've tried using "double[]" and "Object[]" when declaring my array however those will not pass.
I'm not sure how to convert/declare a "System.Array".
Object[] filledVals = new Object[9];
xyz.getDoubleArray("NumVoids", out filledVals); //where .getDoubleArray(string, System.Array)
Simply declare it as System.Array:
Array filledVals;
xyz.getDoubleArray("NumVoids", out filledVals);
Since it is an out parameter, you don't need to initialize it as it must be initialized by getDoubleArray.
To convert it to a double[] you can use this:
double[] result = filledVals.OfType<double>().ToArray();
You can use LINQ:
System.Array result;
xyz.getDoubleArray("NumVoids", out result);
var filledVals = result.OfType<double>().ToArray();

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

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

Passing Arrays by Value and by Reference

These are example from a c# book that I am reading just having a little trouble grasping what this example is actually doing would like an explanation to help me further understand what is happening here.
//creates and initialzes firstArray
int[] firstArray = { 1, 2, 3 };
//Copy the reference in variable firstArray and assign it to firstarraycopy
int[] firstArrayCopy = firstArray;
Console.WriteLine("Test passing firstArray reference by value");
Console.Write("\nContents of firstArray " +
"Before calling FirstDouble:\n\t");
//display contents of firstArray with forloop using counter
for (int i = 0; i < firstArray.Length; i++)
Console.Write("{0} ", firstArray[i]);
//pass variable firstArray by value to FirstDouble
FirstDouble(firstArray);
Console.Write("\n\nContents of firstArray after " +
"calling FirstDouble\n\t");
//display contents of firstArray
for (int i = 0; i < firstArray.Length; i++)
Console.Write("{0} ", firstArray[i]);
// test whether reference was changed by FirstDouble
if (firstArray == firstArrayCopy)
Console.WriteLine(
"\n\nThe references refer to the same array");
else
Console.WriteLine(
"\n\nThe references refer to different arrays");
//method firstdouble with a parameter array
public static void FirstDouble(int[] array)
{
//double each elements value
for (int i = 0; i < array.Length; i++)
array[i] *= 2;
//create new object and assign its reference to array
array = new int[] { 11, 12, 13 };
Basically there is the code what I would like to know is that the book is saying if the array is passed by value than the original caller does not get modified by the method(from what i understand). So towards the end of method FirstDouble they try and assign local variable array to a new set of elements which fails and the new values of the original caller when displayed are 2,4,6.
Now my confusion is how did the for loop in method FirstDouble modify the original caller firstArray to 2,4,6 if it was passed by value. I thought the value should remain 1,2,3.
Thanks in advance
The key to understanding this is to know the difference between a value type and a reference type.
For example, consider a typical value type, int.
int a = 1;
int b = a;
a++;
After this code has executed, a has the value 2, and b has the value 1. Because int is a value type, b = a takes a copy of the value of a.
Now consider a class:
MyClass a = new MyClass();
a.MyProperty = 1;
MyClass b = a;
a.MyProperty = 2;
Because classes are reference types, b = a merely assigns the reference rather than the value. So b and a both refer to the same object. Hence, after a.MyProperty = 2 executes, b.MyProperty == 2 since a and b refer to the same object.
Considering the code in your question, an array is a reference type and so for this function:
public static void FirstDouble(int[] array)
the variable array is actually a reference, because int[] is a reference type. So array is a reference that is passed by value.
Thus, modifications made to array inside the function are actually applied to the int[] object to which array refers. And so those modifications are visible to all references that refer to that same object. And that includes the reference that the caller holds.
Now, if we look at the implementation of this function:
public static void FirstDouble(int[] array)
{
//double each elements value
for (int i = 0; i < array.Length; i++)
array[i] *= 2;
//create new object and assign its reference to array
array = new int[] { 11, 12, 13 };
}
there is one further complication. The for loop simply doubles each element of the int[] that is passed to the function. That's the modification that the caller sees. The second part is the assignment of a new int[] object to the local variable array. This is not visible to the caller because all it does is to change the target of the reference array. And since the reference array is passed by value, the caller does not see that new object.
If the function had been declared like this:
public static void FirstDouble(ref int[] array)
then the reference array would have been passed by reference and the caller would see the newly created object { 11, 12, 13 } when the function returned.
What a confusing use of terms!
To clarify,
for a method foo(int[] myArray), "passing a reference (object) by value" actually means "passing a copy of the object's address (reference)". The value of this 'copy', ie. myArray, is initially the Address (reference) of the original object, meaning it points to the original object. Hence, any change to the content pointed to by myArray will affect the content of the original object.
However, since the 'value' of myArray itself is a copy, any change to this 'value' will not affect the original object nor its contents.
for a method foo(ref int[] refArray), "passing a reference (object) by reference" means "passing the object's address (reference) itself (not a copy)". That means refArray is actually the original address of the object itself, not a copy. Hence, any change to the 'value' of refArray, or the content pointed to by refArray is a direct change on the original object itself.
All method parameters are passed by value unless you specifically see ref or out.
Arrays are reference types. This means that you're passing a reference by value.
The reference itself is only changed when you assign a new array to it, which is why those assignments aren't reflected in the caller. When you de-reference the object (the array here) and modify the underlying value you aren't changing the variable, just what it points to. This change will be "seen" by the caller as well, even though the variable (i.e. what it points to) remains constant.
idea for you all there with knowledge of .net open sources to implement the logics;
//Sample Code, Illustration;
Method1(params dynamic[] var1) {
var1[0]=new dynamic[3] { 1,2,3 }
}
the var1 is not specified or cannot be ref ?
a usage scenario would be ...
//Sample Code, Illustration;
dynamic[] test = new dynamic[];
Method1( ref test,x,x,x,x );
System.Windows.MessageBox.Show( test[2].ToString() );
to indicate ref only when, not being a parameter specific;
and a ref to array items;
//result is IndexOutOfBounds;
this is only a illustrationm it can be done by returning a array and use like:
test = Method1( test,... );
instead of :
Method1( ref test,x,x,..., ref test[x], ref test2, ... );

Unable to understand array behaviour

Try:
Array[] UserInformation;
UserInformation[0] = "Test";
but i get a error Cannot implicitly convert string to System.Array
But this works:
string[] asp;
asp[0] = "ram";
I don't want to use string[] or int[] because I have to assign different data types in each index.
If its not the right way to add items to an array please suggest the correct way?
Array is a type that exists in the BCL - you are looking for an object array, which you also need to initialize:
object[] UserInformation = new object[10];
UserInformation[0] = "Test";
Array[] UserInformation;
This declares UserInformation as an array of arrays... A string is not an array.
You'll need to create an array of "object", since everything in C# inherits from that base class.
object[] anArray = new object[];

Assigning unassigned string to array

I've got a function which takes a ArrayList and loads it with strings along the line of
void func( ref ArrayList data )
{
if( data[0].GetType() == typeof(String) )
data[0] = "Jimmy";
}
In the function that calls func() I am having to create strings to put in the array:
ArrayList data = new ArrayList(1);
string str = "";
data.Add(str);
Is it possible to give the ArrayList the object types without having to create an object of that type? This:
ArrayList data = new ArrayList(1);
string str;
data.Add(str);
Gives a "Use of unassigned local variable 'str'" error.
#James and Guffa: Thanks for the 'stylistic' hints, I'm new to c# and the advice is much appreciated
No, that is not possible. What you want is a reference that points to a string, and that is only possible if it actually points to a string. The fact that the variable that holds the reference is declared as a string reference doesn't matter once you have copied the reference from the variable to the list.
I think that you should rethink the entire concept. I don't know your reason for sending in a list of values and replace them like that, but there has to be a more object oriented way of doing it.
The ArrayList class is practically obsolete, you should use a generic List<T> instead (even if you can't find any other common base class than object).
As you are always sending in a list object to the method and not replacing it with a new list object, you should not use the ref keyword. That's only for when you want to change the reference to the list, not the contents of the list.
You can send two parameters, one ref ArrayList in which members will be assigned and the other an ArrayList and the called function can assign at indexes in data where the type is String
If you are only wanting to keep this type safe then could you not use a List<T> class here instead e.g. List<string>?
What you're trying to do in your method with the above code is to call GetType() on null, which is not possible.
Why not use a generic list List<string> in this case? You can elegantly skip the part of using GetType() to determine the type with this approach:
static void func(List<string> data)
{
if(data.Count > 0)
data[0] = "Jimmy";
}
static void Main(string[] args)
{
List<string> lst = new List<string>(1);
string str = "";
lst.Add(str);
func(lst);
System.Console.WriteLine(lst[0]); //Prints out 'Jimmy'
}

Categories

Resources