5

Given the following C# code:

var a = new[] {"123", "321", 1}; //no best type found for implicitly typed array

And its counterpart in VB.NET:

Dim a = {"123", "321", 1} 'no errors

It appears that VB.NET is able to correctly infer type of a = Object(), while C# complains until the above is fixed to:

var a = new object[] {"123", "321", 1};

Is there a way to auto-infer type in C# for the above scenario?

EDIT: Interesting observation after playing with different types in a C# sandbox - type is correctly inferred if all elements have common parent in the inheritance tree, and that parent is not an Object, or if elements can be cast into a wider type (without loss of precision, for example Integer -> Double). So both of these would work:

var a = new[] {1, 1.0}; //will infer double[]
var a = new[] {new A(), new B()}; //will infer A[], if B inherits from A

I think this behavior is inconsistent in C#, because all types inherit from Object, so it's not a much different ancestor than any other type. This is probably a by-design, so no point to argue, but if you know the reason, would be interesting to know why.

Victor Zakharov
  • 25,801
  • 18
  • 85
  • 151

3 Answers3

9

No. Implicitly typed arrays in C# require that the type of one of the expressions in the array initializer is of the target type. Basically, the compiler tries to find exactly one element type such that all the other types can be converted to it.

You could cast any of the elements to object of course:

var a = new[] { (object) "123", "321", 1}; 

... but then you might as well just use an explicitly typed array initializer:

var a = new object[] {"123", "321", 1}; 

Or in cases where you really are declaring a variable at the same time:

object[] a = {"123", "321", 1};
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
2

No. However, you can make VB behave more like C# by using Option Explicit On, Option Strict On, and Option Infer Off.

Best Practices: Option Infer

Community
  • 1
  • 1
Josh C.
  • 4,303
  • 5
  • 30
  • 51
  • Can I make C# behave more like VB? – Victor Zakharov Nov 20 '12 at 23:46
  • 2
    +1 @Josh C: I wouldn't say "you can", but "you have to!" @Neolisk: use the the new _dynamic_ keyword `dynamic[] k = { "123", "1", 1 };` Now you have a "something" ... – igrimpe Nov 21 '12 at 06:01
  • +1 Option Explicit **must** be on! Option Strict should **almost always** be on. But you might want to leave Option Infer On otherwise you can't use LINQ. – MarkJ Nov 21 '12 at 08:07
  • @igrimpe: `dynamic` is interesting. Not exactly the same as `Dim k() = {...}`, but please post as an answer, so I'll upvote it. – Victor Zakharov Nov 21 '12 at 12:21
1

In C# you could use dynamic: dynamic[] k = { "1", 2, "3" };

It doesn't mimic VB's behaviour completey, though. dynamic[] k = { "1", "2", "3" }; still gives you an array of object, while in VB you get an array of String.

And of course:

dynamic[] k = { "1", "3", "3" };
int i = k[0].I_do_not_exist();

compiles without problem, but most likely will fail miserably ;)

igrimpe
  • 1,775
  • 11
  • 12