为什么我不能将对象(实际上是object [])转换为string []?

leo*_*ora 8 c# arrays casting object

我有一个'对象'类型的字段.当我在visual studio的Watch窗口中检查它时,我看到它的Object [],当我钻进元素时,我看到每个元素都是一个字符串.

但是当我尝试将其转换为String []时,我收到此错误:

无法将'MyObject'(其实际类型为'object []')转换为'string []'string []

有什么理由我不能做这个演员?将此对象转换为字符串数组的最佳方法是什么?

Eri*_*ert 23

这是C#特别令人困惑的特性.这是交易.

在整个讨论过程中,我们假设数组的元素类型是引用类型,而不是值类型.

C#支持不安全的数组协方差.这意味着如果你有一个字符串数组,你可以将它转换为一个对象数组,因为一个字符串可以转换为一个对象:

string[] a1 = { "hello", "goodbye" };
object[] a2 = a1; // Legal
Run Code Online (Sandbox Code Playgroud)

如果你然后尝试从a2中获取一个元素,它可以工作:

object o3 = a2[0]; 
Run Code Online (Sandbox Code Playgroud)

这是合法的,因为a2[0]它确实a1[0]是一个字符串,可以转换为对象.

但是,如果您尝试写入数组,那么您将在运行时收到错误:

a2[0] = new object();
Run Code Online (Sandbox Code Playgroud)

这在运行时失败,因为a2实际上是一个字符串数组,并且您不能将非字符串放入字符串数组中.

所以C#已经被打破了; 可以编写一个编译并看起来正常的程序,但在运行时突然崩溃并出现类型异常,因为您试图将对象放入实际上不是对象数组的对象数组中.

你想要的功能甚至更糟糕,谢天谢地C#不支持它.你想要的功能是:

object[] a4 = { "Hello" };
string[] a5 = a4; 
Run Code Online (Sandbox Code Playgroud)

这将是不安全的阵列逆转.它像这样打破了可怕的:

a4[0] = new Customer(); // Perfectly legal 
string s6 = a5[0]; 
Run Code Online (Sandbox Code Playgroud)

现在我们只是将Customer复制到string类型的变量中.

你应该避免任何类型的阵列协方差或逆变; 正如你所发现的那样,阵列逆变是不合法的,并且阵列协方差在你的程序中制造出意外消失的时间炸弹.首先创建正确类型的数组.

  • @kvb:我明白你的观点.我说它"更加破碎",因为在协变的情况下,破碎的场景是:转换 - 后续写入失败.但是,由于许多人使用数组作为*有效*只读数组 - 它们只在创建数组时写入 - 没有转换 - 后续写入,只有转换后跟读取.也就是说,如果转换后有*write*,它只能*中断.但逆变情况可以在转换后的任何*读取中断; 数组可能不是所有字符串开头! (4认同)

L.B*_*L.B 16

string[] newarr =  Array.ConvertAll(objects, s => (string)s);
Run Code Online (Sandbox Code Playgroud)

- 编辑 -

因为你说我有一个object(知道它object[]实际上是)

string[] newarr =  Array.ConvertAll((object[])objects, s => (string)s);
Run Code Online (Sandbox Code Playgroud)