我试图理解:
Object obj = "string";
var type = obj.GetType(); // returns System.String
我知道这是一个成功的隐式转换,但我不明白为什么如果调用obj.GetType()
它会返回System.String
而不是System.Object
。
如果我想有一个字符串类型,我不会将"字符串"分配给Object
类型。如果obj
保持Object
类型会更正确。谁能解释一下?
您有一个string
文字,其类型为string
。当你把它赋给obj
变量时,它是一个object
,string
文字被隐式转换为object
,这是有效的,因为所有的类类型都隐式继承自object
。
所以你有一个object
但obj
引用的对象的基础类型仍然是string
.通过将其转换为object
,您只是在制作编译器将obj
视为object
,而不是string
。因此,例如,不能使用obj
调用在string
类型上声明的方法。
obj.GetType()
返回基础类型,而不是将对象转换为的类型。这就是为什么你变得string
而不是object
.
因为它是参考转换。顾名思义,在引用转换中,唯一更改的是引用,即指向对象的变量。
构成字符串文字"string"
的位不会更改,您Object o = "string"
唯一要做的就是创建一个指向string
"string"
o
类型化Object
变量。存储在变量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
,因为o
和e
都指向完全相同的对象:"Hello"
。
现在,这不是唯一可能发生的转换。有大量的转换不是参考转换或身份保留转换。一个例子?所有用户定义的转换(implicit
或explicit
运算符):
int i = 1;
double d = i;
d.GetType() //returns Double.
为什么?由于i
和d
是两个不同的对象,因此构成整数和双精度的位完全不同。从int
到double
的隐式强制转换是用户定义的运算符:
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()
仍将返回原始对象的类型。你能告诉我是哪一个吗?
此外,涉及值类型的引用转换是不可能的,正是因为值类型变量的值不是引用,而是值类型实例本身。
实际上,由于C#中的所有内容都继承自object
,因此一切都是对象。例如,string
类型派生自对象(有关详细信息,请查看此内容:值类型继承自 System.Object...为什么?这意味着,每个字符串都是一个对象 - 因此可以隐式转换为对象。但是,它仍然是一个字符串 - 它只是被视为一个对象。
字符串实际上保留在其核心中仍然是字符串,即使您尝试将其转换为对象 - 这对于每个继承项都是相同的。例如,如果您有以下代码:
public class Class2 : Class1
{
}
public class Class1
{
}
并在其他地方执行以下代码(我使用了交互式)
((Class1)new Class2()).GetType()
结果你仍然会得到Class2
。
实际上,我认为不可能这样做 - 你总是可以假装它是另一种类型,我看不出有任何理由认为这是不够的。