Without initialization how is it possible to assign values to arrays?
string[] s={"all","in","all"};
I mean why did not the compile show error?.Normally we need to
initialize ,before assign values.
It's just syntactic sugar.
This:
string[] s = {"all","in","all"};
is compiled to the same code as:
string[] tmp = new string[3];
tmp[0] = "all";
tmp[1] = "in";
tmp[2] = "all";
string[] s = tmp;
Note that the array reference is not assigned to s until all the elements have been assigned. That isn't important in this particular case where we're declaring a new variable, but it would make a different in this situation:
string[] s = { "first", "second" };
s = new string[] { s[1], s[0] };
The same is true for object and collection initializers - the variable is only assigned at the end.
It is possible to declare an array variable without initialization.
Check this out
http://msdn.microsoft.com/en-us/library/0a7fscd0%28VS.71%29.aspx
You aren't "assigning a value to array". You are initializing a variable of type "reference to array". The value with which you initialize it is a reference to an array which was created by the use of short array initializer syntax {...}. While it is only permissible in initializer of variables of array type, it is exactly equivalent to new T[] { ... }, where T is deduced from type of variable.
I think you want to know why
string[] s={"all","in","all"};
works when you would expect to be required to initialize the array first like this :
string[] s = new string[];
or
string[] s = new string[] {"all","in","all"};
The answer is just compiler magic. The compiler knows based on the initialization how big to make the array so it just does it behind the scenes for you. Much like the var keyword, the point is to limit the amount of redundant information you're required to type.
The {"all","in","all"} part is the initialization. the new string[] part can be omitted because the curly braces and string are short hand notation. Take a look at MSDN on Single Dimension Arrays.
string[] s = new string[] { "all","in","all"};
and its shorthand version
string[] s = {"all","in","all"};
are the same thing. See MSDN (Initializing Arrays section) for more detail.
You don't need the new string[] part in C#3 or higher - this works fine
string[] s = { "all","in","all"};
It's just a case of the compiler being a bit smarter and working out what you mean - the back end IL will be the same.
You can do so simply because it is allowed, doing so in two steps is not necessary so this is the shorthand. Consider it sugar.
Related
I have been wondering, why isn't my method, modifying the array, when I used it as a parameter and made it equal to another array with different values, inside the method?
Am I just changing the reference address?
static void Main()
{
string[] array = { "yes", "no", "maybe" };
TestO(array); // Still "yes", "no", "maybe"
}
static void TestO(string[] array)
{
string[] secondArray = new string[array.Length];
secondArray[0] = "1";
secondArray[1] = "2";
secondArray[2] = "3";
array = secondArray;
}
My guess: I did not modify the array inside the Main(), because when doing array = secondArray; in the Test0() method,
I just changed the reference address of array to secondArray.
If my guess is not right, my question is, why exactly is it not getting modified?
(I know that I can just modify Test0() to a string[] return method and return the modified secondArray and pass it on to the array in Main())
Another questions is:
If I use the string[] return method, and declare the following:
static void Main()
{
string[] array = { "yes", "no", "maybe" };
array = TestO(array);
}
static string[] TestO(string[] methodArray)
{
string[] secondArray = new string[methodArray.Length];
secondArray[0] = "1";
secondArray[1] = "2";
secondArray[2] = "3";
return secondArray;
}
array = TestO(array); am I just passing the reference address of the secondArray[] to array[] or am I passing only the values of it? (Most probably it will be the reference address, but I wanted to be sure if mistaken)
I just changed the reference address of array to secondArray. If my guess is not right, my question is, why exactly is it not getting modified?
I think you're leaning towards appreciating that there are two references to one data in memory (there are not two data); you have a variable array that points to data. You call a method and another, copy reference is established to the same data. You made a new object, then you pointed the copied reference at the new object, leaving the original reference pointing to the original data, then you threw the copy reference and the new data away.. You're back to the exact same situation you started with.
Pictorially, line by line, it might look like (I renamed your method argument to arrayX so the difference is obvious):
If you decorate the argument with ref and call it with ref there is no copy, so the called method can modify the original reference and point it somewhere else:
Note that in either of these cases it's perfectly possible to modify the contents of the array. Doing:
arrayX[0] = "New data";
..would take effect in either case and printing array[0] would show "New data". When modifying the data at the end of the arrow it matters not whether the starting point is an original reference or a copy. This is purely about whether the method has the power to point the original reference passed to it, to a different object or not
Generally we don't do it. We adopt the style of your second code block - to return the data. It may help to see it as rude - imagine your friend says he'll look after your plant while you're on holiday; you give your keys to your friend. He swaps your plant for a different one that he likes better; you're upset because you had that plant for ten years..
There are very few reasons to use ref, or the related "power to overwite your reference" - out. Don't use it for "I wanted to return multiple things from my method" - in an OO world we can always return one thing that represents two items of data. We don't need to "return two things"; we can return one thing with two things inside it...
//don't:
void GetPerson(ref string name, ref int age)
//consider a class:
Person GetPerson()
return new Person(){ Name = ..., Age = ...}
//or a Tuple
(string Name, int Age) GetPerson
Let the calling method choose whether its own variable should be overwritten, rather than having some "third party" pull that rug from under its feet
you don't need to return anything , just use a ref
static void Test( ref string[] array)
{
string[] secondArray = new string[array.Length];
secondArray[0] = "1";
secondArray[1] = "2";
secondArray[2] = "3";
array = secondArray;
}
When you pass an array to a method
static void Test0(string[] array)
{
You are passing a reference to that array. That reference is effectively immutable (you're getting a copy of the reference, not the original one), so you can't change the parameter reference and expect it to affect the code outside of the Test method.
While you can do this to get the behavior you want:
static void Test0(ref string[] array)
{
it's not considered good C# style. Strings are themselves immutable; the "correct" style is to return them from the method. This is also true of string arrays.
The only thing you would be saving by using this technique is an extra reference and a return statement, since you're still creating new strings and a new array anyway.
Okay, I'll caveat this question with two things. One, I'm not as smart as you (I'm really not). Second, I may have found an answer to my own question, but want to verify.
I'm attempting to declare multiple arrays at the same time. It looks something like this. The first is just declaring a single array, while the second tries to declare both profit_Normal and profit_High in the same line:
double [] tradeType_Active = new double [15];
double [] profit_Normal, profit_High = new double [5];
Can I do this? I currently use this syntax for declaring non-array values with commas, like this:
double
BUpper,
BUpper_Prev,
BUpper_Prev2;
Please let me know when you have a moment.
Your line of code
double[] profit_Normal, profit_High = new double[5];
does declare multiple double[]. What it doesn't to is to initialize all of them. It initializes only the second one.
If you have the following line:
double[] a, b, c, d = new double[5];
what happens is that you are declaring 4 references of arrays of double. For each array you declare you must initialize it - which you are doing only for the last.
To initialize multiple arrays you need to actually initialize them:
double[] profit_Normal = new double[5], profit_High = new double[5];
The difference between the arrays case and this double BUpper, BUpper_Prev, BUpper_Prev2; is that arrays are reference types that their default value is null and must be initialized, whereas doulbe's default value is 0.
Yes, this is absolutely allowed, as long as you keep [] in the declaration to indicate that you are declaring an array:
double[] a = new double[4], b = new double[5];
The double[] part is the type of variables being declared. In your case, that's an array of double.
Note that the only difference between the above and your second declaration is that you did not initialize the profit_Normal variable.
You can use the same syntax you currently use, but in order to instantiate each one as well as declaring it, it would look like this, with = new double[5] after each one:
double[]
profit_Normal = new double[5],
profit_High = new double[5];
I've seen All possible C# array initialization syntaxes which shows several different ways to initialize an array.
Does the following initialization creates an instance that is different in some ways compared to one created with regular call with new ?
Initialization:
string[] strArray = {"one","two","three"};
Compared to string[] strArray = new String[] {"one","two","three"};
It is a syntactic sugar. The compiler transforms this:
string[] strArray = {"one","two","three"};
To This:
string[] expr_07 = new string[] {
"one",
"two",
"three"
};
Above output is using Roslyn C# compiler.
You can't initialize something that's not there. So yes, a new instance does get created, in the exact same way as though you had written the new operator. It's just a convenience provided by the language for when you're initializing an array at the same time that you're declaring it so you aren't forced to write it out (when doing it in a separate statement, the new operator is required because the compiler can't assume you haven't already assigned an array reference to the variable beforehand — the very bare minimum you can get away with in a separate statement is strArray = new[] {...};).
This could be very easy, but how can I place or convert a string into an array?
The code that I have, is the following:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string one;
string[] two;
one = "Juan";
two = {one}; // here is the error
HttpContext.Current.Response.Write(two);
}
}
And the error is the following:
Compiler Error Message: CS0029: Cannot implicitly convert type 'string' to 'string[]'
Thanks for you help!
Replace this:
two = {one}; // here is the error
With
two = new[] { one };
OR
two = new string[] { one };
The reason you are getting the error is clear from the error message.
See: Object and Collection Initializers (C# Programming Guide)
Later when you are doing Response.Write, you will get System.String[] as output, since two is an array. I guess you need all array elements separated by some delimiter. You can try:
HttpContext.Current.Response.Write(string.Join(",", two));
Which will produce all the elements in the array separated by comma
It looks like you're trying to use initialization syntax for an assignment. This should work:
two = new string[] {one};
or just
two = new [] {one};
since the compiler will infer that you want a string[]
I think you'll also be surprised what Response.Write(two); produces...
You're using the static initializer syntax to try and add an item to your array. That doesn't work. You can use similar syntax to allocate a new array with the value one - two = new string[] { one }; - or you can allocate the array then add elements through assignment like;
string[] two = new string[10];
two[0] = one; // assign value one to index 0
If you do it like this you have to do some bounds checking for example the following will throw an IndexOutOfRangeException at runtime;
string[] two = new string[10];
int x = 12;
two[x] = one; // index out of range, must ensure x < two.Length before trying to assign to two[x]
That syntax ({one}) is only valid if you declare the array variable in the same line. So, this works:
string one;
one = "Juan";
string[] two = {one};
A more common way to initialize an array, which works in more places, is to use the new keyword, and optionally have the type be inferred, e.g.
string one;
string[] two;
one = "Juan";
// type is inferrable, since the compiler knows one is a string
two = new[] {one};
// or, explicitly specify the type
two = new string[] {one};
I usually declare and initialize on the same line, and use var to infer the type, so I'd probably write:
var one = "Juan";
var two = new[] { one };
Is it possible to know the length of a string array - without having an object instance - via reflection?
E.g. in this case: 2.
public string[] Key
{
get { return new string[] { Name, Type }; }
}
EDIT: ok, I will not try to do this, it doesn't make much sense.
Perhaps you mean "without having the exact type of the Array". C# Arrays all derive from Array, so you can cast an Array reference to Array and use the Length property.
If you TRULY wants to reflect the property,
var type = typeof(MyClass);
var prop = type.GetProperty("Key");
var method = prop.GetGetMethod();
var body = method.GetMethodBody();
var ils = body.GetILAsByteArray();
from here you'll have to use one of the various libraries to decode bytes to IL OpCodes (for example https://gist.github.com/104001) . The OpCode you are looking for is newarr. The last push of an int32 before the newarr is the size of the array.
You have two things going on there... telling the length of an array is pretty simple once you have an array; you just call .Length (in the case of a vector).
However, you mention an instance, and you are showing an instance property; which makes me think it is the containing object you lack. In which case... no. You can't make a virtcall on a null instance. And trying to use static-call on an instance member of a class is very evil; IIRC the runtime will kick you for this.
You could, however, make it a static property just by adding the static modifier. Then you just pass in null as the instance to reflection.
I guess you mean you want to know the size of the array the property will return if it were called?
I don't think you can do it sensibly.
If the property had a conditional then it could return different sized arrays, so
you'd have to evaluate the property to know the size. Which could have side effects or be dependent on other values in the object (or statics).
Consider this one:-
static public int n;
public string[] Key
{
get {
if (n > 1)
return new string[] { "Name", "Type" };
else
return new string[] { "Name", "Type", "Cheese" };
}
}
Basically, you'd have to run the code.