Tech Off Thread

83 posts

C# array constructor & initialization

Back to Forum: Tech Off
  • User profile image
    janzenr

    Hello all,
    The question is on line 3:

    class Program {
       static void Main(string[] args) {
          //new Object[] { foo() };  If I uncomment this line, why does it not compile?
          bar(new Object[] { });
          bar(new Object[] { foo() });
          Console.ReadKey();
       }
       public static object foo() {
          Console.WriteLine("foo"); // A side effect
          return default(object);
       }
       public static void bar(Object o) {
          Console.WriteLine("bar");
       }
    }

    should output:

    foo
    bar
    foo
    bar

    but it does not compile.  It gives the compiler error:

    "Only assignment, call, increment, decrement, and new object expressions can be used as a statement"

    The Answer:

    new Object[] { } is(or treated as) an expression not a statement.
    The Array initializers do not have any side effects.
    Edit:
    They are not "new object expressions".

    i++ is also an expression, but there is an exemption for increment and decrement operators. (See the error message.)

    This is why you can use new Object[] { } as a parameter to a function, or assign it's value to a variable, but not as a statement;
    For more details, see pages 2 and 3 and the response from the C# team in blue on page 3. (Assuming default forum settings.)






    Edit: (Poorly worded stuff)
    Hello all,
    I am trying to figure out the intricacies of the following code:

       class Program {
         static void Main(string[] args) {
           new Object(); // This compiles
           new Object[] { }; // This does not compile. Why not?  Is this not syntactic sugar for array creation & initialization?
           (new Object[] { }).GetType(); // This compiles.
         }
       }

    The second line gives me:

    "Only assignment, call, increment, decrement, and new object expressions can be used as a statement"

    Any ideas?

    After some even more confusion:

    I will restate my question:

    Why does the C# compiler allow statements like:
    new String(); (This does throw an error because there is no no-argument constructor for String, but feel free to replace Object for String in any of these examples.  My mistake.  The spirit of the question is the same.  The original code at the top is correct.)
    and
    (new String[] { "foo", "bar"}).GetType();
    and
    Console.WriteLine(new String[] { "foo", "bar"});
    but not:
    new String[] { "foo", "bar"};

    The last example gives me:
    "Only assignment, call, increment, decrement, and new object expressions can be used as a statement"

    I do not understand why the last statement does not compile.

    To further clarify, Section 1.6 on Objects of the C# specification states:
    "Instances of classes are created using the new operator, which allocates memory for a new instance, invokes a constructor to initialize the instance, and returns a reference to the instance."

    Section 1.8 on Arrays states:
    "Actual array instances are created dynamically at runtime using the new operator."

    Does this imply that the new operator is overloaded?

    Also, it looks like one can only declare an array if it is immediately bound to a variable, in contrast to where one can create an object even if it is not immediately bound to a variable. Ex:

    new String(); and new String[] { "" }; are both not bound.
    new String(); compiles and new String[] { "" }; does not.

    It appears that when using new String[] { "" } as an argument, as in Foo(new String[] { ""}); causes new String[] { "" } to be bound to the single argument of function Foo
    and then the compiler does not complain.

    If C# does indeed exhibit this strange variable binding behaviour, why is C# this way?

    I am starting to think I asked at the wrong place.

  • User profile image
    littleguru

    the array initializer in C# 3.0 would look like this:

    var a = new[] { "foo", "bar" };
    or
    string[] a = new[] { "foo", "bar" };
    or even
    string[] a = new string[] { "foo", "bar" };

    you need a variable + type on the left hand side of the =, which you don't in the second line. This might be a little bit special for array. In the third line you only get the type for that thing... it's a different thing.

  • User profile image
    janzenr

    I do not understand your response.  There are no '=''s in this code at all.

  • User profile image
    littleguru

    it makes sense to do for example:

    if (new Foo().Blah(...))

    it doesn't make sense to do:

    if (new Foo[10].SomeMethod(...))

    If you create an instance of an object (not an array) you can use the instance to call directly methods on it... Not very nice, but you can. On arrays it doesn't make any sense that's why it is not possible. An array usually is constructed and you populate it with instances afterwards... that's what makes sense.

  • User profile image
    littleguru

    typeof(...) returns also an instance of a type that you can call methods on and which makes sense...
    for example:

    if (typeof(Foo).GetProperty("blah") != null)

  • User profile image
    littleguru

    this works btw:

    var a = new string[] { "foo", "bar" }.Intersect(new string[] { "bar" });

    or

    if (new string[] { "foo", "bar" }.Intersect(new string[] { "bar" }).Count() > 0)

    why would you need to do what you did in your code sample with an array?

  • User profile image
    janzenr

    The question is to not about why I would need to do this, but why it would not compile.  It is a language thing.

    I figure if:
    new String();
    can compile then:
    new String[] { };
    should also.

    I am not concerned about what works.  I want to know why this does not work.

  • User profile image
    littleguru

    OK, short answer: it is a language thing.
    longer answer: before the initializer it didn't make any sense to use an empty array without assigning it...

    i only tried to explain it to you...

  • User profile image
    janzenr

    Ok then, let's remove the empty part:
    new Object[] { "foo", 5, new Object() };
    It is not empty, & still will not compile.

  • User profile image
    littleguru

    Still... what sense does that make?

  • User profile image
    janzenr

    My question is not about whether it makes sense. 

    In fact, it makes no more sense to do this:
    new Object();
    than this:
    new Object[] {"foo", 5, 2.22};

    The question is, why is the first statement allowed, and the second disallowed in C#.

  • User profile image
    janzenr

    I think you are a misunderstanding me.  This has nothing to do with whether or not the array is empty.

  • User profile image
    littleguru

    You probably need to ask the language team and they probably had some design decisions why they wanted the compiler to inform you that an empty array is not allowed.

  • User profile image
    littleguru

    Tell me why you think it is not possible... I have tried to find it in the C# language specification but can't find it. I really don't know why this is giving an error other than I don't see why it would make any sense to use it and therefore guessing that they disabled it because it doesn't make any sense. It works great if you call a method on the initialized array...

    It doesn't make any sense to disable it from the .NET standpoint. At least not to me... it seems to me as it is a design decision that the C# team made and therefore not possible.

  • User profile image
    janzenr

    I was hoping that someone would give me a definite answer as to why the compiler would not accept that code though.  The "It does not make any sense" argument does not hold because then:
    new Object();
    should not be allowed either, right?

  • User profile image
    littleguru

    Can you perhaps send me an e-mail? I can probably ask the team for you, if you want... and post the results here. But please send me a mail and I'll try to get back with the results to you asap.

  • User profile image
    Johnny​Awesome

    Compiler questions have baffled me before as well. I certainly do not have answer for you, but you are not alone.

  • User profile image
    janzenr

    Thanks, JohnnyAwesome, for the understanding reply.

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.