4

I've got a mysterious compile error with the following test case:

[TestCase(new byte[259], new byte[] { 0, 0, 0, 0, 255 })]
public void EncodeTest(byte[] source, byte[] expected) {
    ...
}

error CS0182: An attribute argument must be a constant expression,
typeof expression or array creation expression of an attribute parameter type

If I replace the first argument of the attribute as follows:

[TestCase(new byte[259] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                          0, 0, 0 },
              new byte[] { 0, 0, 0, 0, 255 })]
public void EncodeTest(byte[] source, byte[] expected) {
    ...
}

it compiles just fine. Why?

Update: Let me clarify the problem. If you write code like the following:

int[] arr = new int[259];
Console.Write(arr[0]); // 0

no compile error occurs since the compiler (or CLR?) implicitly initializes every element with the default value.

  • Visit http://stackoverflow.com/questions/10445663/c-what-is-a-constant-expression – Satpal Jul 08 '13 at 13:05
  • You should focus a bit on the practical usage of an attribute that takes an uninitialized array. There's just no point, you might as well create that array in the attribute constructor. – Hans Passant Jul 08 '13 at 13:07
  • @HansPassant It looks like that attribute might be NUnit-related and not under the OP's control. Even if not, I think it's still worth asking why there's a discrepancy in behaviour between two expressions which the spec (by my reading anyway) claims should be identical. – anton.burger Jul 08 '13 at 15:29

1 Answers1

0

In your first construction, you simply declared an array of 259 bytes, but it's uninitialized. Sure, the CLR will automatically initialize intrinsic values (actually, this is an array, so it's not even intrinsic, it's an object--the byte[] keyword (and operator) is just syntactic sugar to make writing and reading code easier. In fact, if you'd written Array<System.Byte> someArray;, someArray would be null until you initialized it, e.g. someArray = new Array<System.Byte>(259);.

Attributes, as the error states, requires constants (or something that can be made constant) as a parameter.

A declared array is just that, a declaration. Is there anything in it? You haven't said so, but the compiler can't assume you want a zero-filled array. You must tell it explicitly what value to use. Attributes are evaluated at compile-time and adorn/decorate code constructs providing meta-data (or additional functionality to provide) to various code constructs you've used them with.

gingerbreadboy
  • 7,386
  • 5
  • 36
  • 62
fourpastmidnight
  • 4,032
  • 1
  • 35
  • 48
  • 2
    `int[] arr = new int[259];` implicitly initializes every element with the default int value 0. There's no need to append `{ 0, 0, 0, ..., 0 }`. I still don't get why they are different. – Bang Jun-young Jul 08 '13 at 13:23
  • 1
    @fourpastmidnight The error actually specifically says that constant expressions are only one kind of permissible attribute argument, and that another is "array creation expressions of an attribute parameter type". From the perspective of the spec, there *seems* to be no difference between the two expressions used in the question; as the OP says, the short form initialises every element with its default value. – anton.burger Jul 08 '13 at 15:06
  • Yeah, you're all right..there shouldn't be a difference. Good call. In fact, I missed the `new` keyword in the OP..in any event, if it had been forgotten, it would've been a different compile-time error. – fourpastmidnight Jul 08 '13 at 16:23