【问题标题】:C# - Why convert a type to object works like this?C# - 为什么将类型转换为对象会这样工作?
【发布时间】:2017-09-19 12:37:51
【问题描述】:

我正在努力理解:

Object obj = "string";
var type = obj.GetType(); // returns System.String 

我知道这是一个成功的隐式转换,但我不明白为什么如果调用 obj.GetType() 它返回 System.String 而不是 System.Object

如果我想要一个字符串类型,我不会将“字符串”分配给Object 类型。如果obj 仍然是Object 类型会更正确。谁能解释一下?

【问题讨论】:

标签: c# oop type-conversion


【解决方案1】:

你有一个string 字面量,它的类型是string。当您将其分配给 object 变量 obj 时,string 文字会隐式转换为 object,这是有效的,因为所有类类型都隐式继承自 object

所以你有一个object,但obj 所指的对象的基础类型仍然是string。通过将其转换为object,您只是在使编译器将obj 视为object,而不是string。因此,例如,您不能使用 obj 调用在 string 类型上声明的方法。

obj.GetType() 返回基础类型,而不是您将对象转换成的类型。这就是为什么你得到string 而不是object

【讨论】:

  • “当你将它分配给作为对象的 obj 变量时,字符串文字被隐式转换为对象”。这不是真的,字符串文字不会转换为任何东西。参考是。
【解决方案2】:

实际上,由于 C# 中的所有内容都继承自 object,因此所有内容都是一个对象。例如,string 类型派生自对象(请查看此以获取更多信息:Value types inherit from System.Object...why?)。这意味着,每个字符串 都是 一个对象 - 因此可以隐式转换为一个对象。但是,它仍然是一个字符串 - 它只是被视为一个对象。

字符串实际上仍然保留在其核心中,即使您尝试将其强制转换为对象 - 这对于每个继承项都是相同的。例如,如果您有以下代码:

public class Class2 : Class1
{

}

public class Class1
{

}

并在其他地方执行以下代码(我使用了交互式

((Class1)new Class2()).GetType()

结果你仍然会得到Class2

实际上,我认为这样做是不可能的——你总是可以假装它是另一种类型,我看不出有任何理由说明这还不够。

【讨论】:

  • string 不是值类型。
【解决方案3】:

因为它是一个引用转换。顾名思义,在引用转换中,唯一改变的是reference,也就是指向对象的变量。

组成字符串文字"string"的位不会改变,你在Object o = "string"中做的唯一事情就是创建一个变量o键入Objectstring"string"。存储在变量o 中的值正是string 所在的内存地址:

给定:

var s = "Hello";

任何这些转化都是参考转化:

object o = s; //creates a new reference typed object pointing to "Hello".
IComparable<string> e = s; //creates a new reference tpyed...

o.GetType()e.GetType() 都将返回 System.String,因为 oe 都指向完全相同的对象:"Hello"

现在这不是唯一可能发生的转换。有大量的转换不是参考转换或身份保留转换。一个例子?所有用户定义的转换(implicitexplicit 运算符):

int i = 1;
double d = i;
d.GetType() //returns Double.

为什么?因为id 是两个不同的对象,所以构成整数和双精度的位是完全不同的。从intdouble 的隐式转换是用户定义的运算符:

class Bar
{
    public Bar(Foo f) { ... }
}

class Foo
{
    public static implicit operator Bar(Foo f) => new Bar(f);
}

现在如果你这样做:

var f = new Foo();
object o = f;
Bar b = f; //implicit user defined conversion from Foo to Bar

您将获得以下输出:

o.GetType() //Reference conversion: returns Foo
b.GetType() //User defined conversion: returns Bar

请注意,所有引用转换都是由编译器提供的,您不能引用转换定义为用户定义的运算符:

public static implicit operator Object(Foo f) { ... } //compile time error. 

话虽如此,有一种特殊的非身份保留转换,GetType() 仍将返回原始对象的类型。你能告诉我是哪一个吗?

此外,涉及值类型的引用转换是不可能的,正是因为值类型变量的值不是引用,而是值类型实例本身。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    相关资源
    最近更新 更多