Difference in array initialization with and without new operator - c#

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[] {...};).

Related

Array initialization syntax in method call

Having the code below, why is the variable declaration considered as correct syntax, but not also the method call?
public static void Func(string[] p)
{
}
public static void Test()
{
string[] a = { "x", "y", "z" };
Func({"x", "y", "z"});
}
It looks like everybody else is focusing on the workaround (which is simply to specify that you need a new [] { "some", "strings" }. The why is a little less obvious though.
The former is valid because the compiler knows to use your initialization syntax to create an Array (because you've defined it as such).
The later would have some issues. It may seem trivial in this case because the compiler should, theoretically, be able to figure out that you need a string[]. Think about cases where you have a Func<IEnumerable<string>> though. What type gets generated in that case? Would the compiler take a wild-ass guess? Always use an Array (even though there might be a better fit)? It could be one of a number of possibilities.
I'm guessing that's the reason that the language specification doesn't allow for passing things this way.
You need to pass in a value as the argument. {"x", "y", "z"} is not a value. It can be used as short-hand for initializing a variable.
Note that both of these are valid:
List<string> a = new List<string>() {"x", "y", "z"};
string[] b = new string[] {"x", "y", "z"};
And the full version of what it represents:
List<string> a = new List<string>();
a.Add("x");
a.Add("y");
a.Add("z");
So you need to make an object (new)
new [] {"x", "y", "z"}
Or make an object beforehand and pass that in.
As for why this is like this, you need to pass in a value, not a helper for array initialization.
You can initialize the object directly on the inside of the method call, but do not think a good practice.
where you used:
 
Func ({"x", "y", "z"});
The above form you tried to pass an object not instantiated, ie it does not already exist on your "context". The correct is you initialize it to be generated in a reference memory to this value and thus the "Func" method you can use it.
In the case of variable declaration:
string[] a = {"x", "y", "z"};
In this case your compiler is reading:
string[] a = new string[] {"x", "y", "z"};
It does this interpretation alone, without requiring you to do object initialization explicitly.
So my answer is best for this situation you must first create the object then pass it as a parameter to the method:
 
string[] a = {"x", "y", "z"};
  Func (s);

Optional Multidimensional Arrays as Arguments in C#

I want to declare a function that has 1 required argument and 4 optional 2D array arguments, how do i do so? I know to make an argument optional, we should place a value in it during function creation.
I also saw what I did below is wrong and has a "Array initializers can only be used in a variable or field initializer. Try using a new expression instead." Error
private String communicateToServer(String serverHostname,
String[,] disk = new string[] {{"dummy","dummy"}},
String[,] hdd= new string[] {{"dummy","dummy"}}
String[,] nic= new string[] {{"dummy","dummy"}}
String[,] disk = new string[] {{"dummy","dummy"}}
)
It's not possible to do this directly but you can get a similar effect by doing the following pattern
private String communicateToServer(String serverHostname,
String[,] disk = null,
String[,] hdd= null,
String[,] nic= null) {
disk = disk ?? new string[] {{"dummy","dummy"}},
hdd= hdd ?? new string[] {{"dummy","dummy"}}
nic= nic ?? new string[] {{"dummy","dummy"}}
...
}
Essentially use null as the default and if null is the value convert to the actual default. This does mean that an explicit null being passed will be interpreted as the default value though.

c# place string into an array

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

Java Equivalent of C# Anonymous Arrays and Lists?

C# lets me make arrays on the fly when I need to pass them into functions. Let's say I have a method called findMiddleItem(String[] items). In C#, I can write code like:
findMiddleItem(new String[] { "one", "two", "three" });
It's awesome, because it means I don't have to write:
IList<String> strings = new List<String>();
strings.add("one");
strings.add("two");
strings.add("three");
findMiddleItem(strings.ToArray());
Which sucks, because I don't really care about strings -- it's just a construct to let me pass a string array into a method that requires it. A method which I can't modify.
So how do you do this in Java? I need to know this for array types (eg. String[]) but also generic types (eg. List).
A List and an Array are fundamentally different things.
A List is a Collection type, an implementation of an interface.
An Array is a special operating system specific data structure that can only be created through either a special syntax or native code.
Arrays
In Java, the array syntax is identical to the one you are describing:
String[] array = new String[] { "one", "two", "three" };
Reference: Java tutorial > Arrays
Lists
The easiest way to create a List is this:
List<String> list = Arrays.asList("one", "two", "three");
However, the resulting list will be immutable (or at least it won't support add() or remove()), so you can wrap the call with an ArrayList constructor call:
new ArrayList<String>(Arrays.asList("one", "two", "three"));
As Jon Skeet says, it's prettier with Guava, there you can do:
Lists.newArrayList("one", "two", "three");
Reference: Java Tutorial > The List Interface, Lists (guava javadocs)
VarArgs
About this comment:
It would be nice if we would be able to do findMiddleItem({ "one", "two", "three" });
Java varargs gives you an even better deal:
public void findMiddleItem(String ... args){
//
}
you can call this using a variable number of arguments:
findMiddleItem("one");
findMiddleItem("one", "two");
findMiddleItem("one", "two", "three");
Or with an array:
findMiddleItem(new String[]{"one", "two", "three"});
Reference: Java Tutorial > Arbitrary Number of Arguments
In Java you can construct an array in the same way:
findMiddleItem(new String[] { "one", "two", "three" });
You can't construct a List<T> in quite the same way, but there are various ways of getting around that, e.g. wrapping an array, or using some of the Guava Lists.* methods. (Your code trying to call findMiddleItem with an argument of type IList<string> wouldn't have compiled, as an IList<string> isn't necessarily a string[].) For example, if findMiddleItem actually had a parameter of type List<String> you could use:
findMiddleItem(Lists.newArrayList("one", "two", "three"));
As well as not having collection initializers (or object initializers), Java also doesn't have implicitly typed arrays... your original C# code can be condensed in C# 3 and higher:
findMiddleItem(new[] { "one", "two", "three" });
You can do it the exact same way:
findMiddleItem(new String[] { "one", "two", "three" });
is valid in Java. Assuming that findMiddleItem is defined as:
findMiddleItem(String[] array)
The same way as in C# findMiddleItem(new String[] { "one", "two", "three" });
Also, for future reference, you can construct a List in Java in a slightly less-verbose way*:
List<String> myStringList = new ArrayList<String>() {{
add("a");
add("b");
add("c");
}};
* As Sean pointed out, this can be considered bad practice since it does create an anonymous subclass of ArrayList.
I think it's the exact same syntax in Java. This works:
public class Main
{
public static void main( String[] args )
{
method1( new String[] {"this", "is", "a", "test"} );
}
private static void method1( String[] params )
{
for( String string : params )
System.out.println( string );
}
}
I think this will work on non-static methods, too.
Apart from using vargs like
findMiddleItem("one", "two", "three", "four", "five");
you can do
findMiddleItem("one,two,three,four,five".split(","));
EDIT: to turn a String into a List you can use a helper method.
public static List<String> list(String text) {
return Arrays.asList(text.split(","));
}
findMiddleItem(list("one,two,three,four,five"));

Value assignment in C#

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.

Categories