我有一个关于使用new[]
的问题。
想象一下:
Object.SomeProperty = new[] {"string1", "string2"};
一些属性 (SomeProperty) 需要一个字符串数组。
我知道这段代码片段会运转。但我想知道它在内部都做了些什么。new[]
会产生一个object
类的实例,然后在SomeProperty
中会自动将其转换为string
对象吗?
谢谢 (Xièxiè)
我有一个关于使用new[]
的问题。
想象一下:
Object.SomeProperty = new[] {"string1", "string2"};
一些属性 (SomeProperty) 需要一个字符串数组。
我知道这段代码片段会运转。但我想知道它在内部都做了些什么。new[]
会产生一个object
类的实例,然后在SomeProperty
中会自动将其转换为string
对象吗?
谢谢 (Xièxiè)
好的,这里仍然有一点点混淆。
正在进行的推断与对象类型的某些属性无关,而是与数组初始化器中表达式的类型有关。换句话说,您可以这样做:
object o = new[] { "string1", "string2" };
而o仍然将是一个关于字符串数组的参考。
基本上,编译器会看到这样的表达式:
new[] { A, B, C, D, ... }
(其中A,B,C,D等均为表达式)并尝试找出正确的数组类型来使用。它仅考虑A、B、C和D(等)的类型作为数组元素类型。在选择候选类型集合后,它会尝试找到一个所有其他类型都可以隐式转换为的类型。如果没有 仅有一个 这样的类型,编译器将发出警告。
那么例如:
new[] { new Form(), new MemoryStream() }
不会编译 - MemoryStream
和 Form
两者都无法转换为另一个。 然而:
new[] { GetSomeIDisposable(), new MemoryStream() }
将被视为IDisposable[]
,因为存在从MemoryStream
到IDisposable
的隐式转换。同样:
new[] { 0, 1, 3.5 } // double[]
new[] { 1, 3, 100L } // long[]
这只是语法糖。编译器将推断出实际上需要的类型,并创建等效于显式构造的代码:
Object.SomeProperty = new string[] {"string1", "string2"};
在运行时不会执行new[]
这样的东西。
这大致翻译为:
string[] $temp = new string[2];
$temp[0] = "string1";
$temp[1] = "string2";
Object.SomeProperty = $temp;
有趣的是,var x = new[] { "string1", "string2" };
同样有效,它可以推断出 x 是一个 string[]
,但var x = { "string1", "string2" };
失败了。
编译器替换:
Object.SomeProperty = new[] {"string1", "string2"};
和:
Object.SomeProperty = new string[] {"string1", "string2"};
我希望你不会在类型替换和类型推断之间产生混淆!我假设Object.SomeProperty的类型是string[],尽管由于数组协变性,它也可能是object[](请注意,这不是好事情 - 请查看Eric Lippert的这篇文章!)。
编译器使用启发式进行类型推断,它确定“string1”和“string2”是字符串类型,因此它有效地将您的代码替换为:-
Object.SomeProperty = new string[] {"string1", "string2"};
那真的很简单!这一切都在编译时完成,没有一点运行时的操作。