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



我有一个类型为"对象"的字段。 当我在Visual Studio的"监视"窗口中检查它时,我会看到它的Object[],当我钻取到元素时,我看到每个元素都是一个字符串。

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

无法将"MyObject"(实际类型为"object[]")转换为"string[]"字符串[]

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

这是 C# 的一个特别令人困惑的功能。这是交易。

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

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

string[] a1 = { "hello", "goodbye" };
object[] a2 = a1; // Legal

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

object o3 = a2[0]; 

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

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

a2[0] = new object();

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

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

你想要的功能比这更破碎,谢天谢地,C# 不支持它。您想要的功能是:

object[] a4 = { "Hello" };
string[] a5 = a4; 

这将是不安全的阵列逆变。它像这样可怕地破裂:

a4[0] = new Customer(); // Perfectly legal 
string s6 = a5[0]; 

现在我们只是将一个客户复制到字符串类型的变量中。

你应该避免任何类型的数组协变或逆变

;正如你所发现的,数组逆变是不合法的,数组协方差在你的程序中制造出意外爆炸的小定时炸弹。首先制作正确类型的数组。

string[] newarr =  Array.ConvertAll(objects, s => (string)s);

--编辑--

既然你说我有object (知道它实际上是一个object[]

string[] newarr =  Array.ConvertAll((object[])objects, s => (string)s);
object[] original = new object[]{"1", "2"};
//some code in between here
object obj = original ;
object[] objArray = (object[])obj;
string[] newArray = new string[objArray.Length];
for(int i = 0; i < newArray; i++)
{
  newArray[i] = (string)objArray[i];
}

这里的其他答案向您展示了更快/更短的转换方法。 我把整个事情写成这样,因为它显示了真正发生的事情和需要发生的事情。 您应该在实际生产代码中使用一种更简单的方法。

面向对象编程的规则是 -

"派生类始终可以类型转换为基类"和"仅当基类保留的当前实例实际上是派生类时,才能将基类强制转换为派生类"

例如(A 是基数,B 是派生的)

A a = new B();  // legal;
B b = (B) a ;   // legal as "a" is actually B (in first statement)

非法 :>

A a = new A();
B b = (B) a;  // not legal as "a" is A only. 

同样的事情也适用于对象和字符串类。对象是基类,字符串是派生类。

您可以将

实际string[]转换为object[]

这是一个数组协方差

可以在链接中找到一个清晰的例子。

应强制转换集合中的每个元素,而不是集合本身。

object[] ovalues = new object[] { "alpha", "beta" };
string[] svalues = ovalues.Cast<string>().ToArray();

最新更新