为什么我不能将对象(实际上是对象[])转换为字符串[]
本文关键字:对象 转换 字符串 实际上 不能 为什么 | 更新日期: 2023-09-27 18:31:13
我有一个类型为"对象"的字段。 当我在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();