C# 为什么对象的引用无法访问方法和属性

C# 为什么对象的引用无法访问方法和属性,c#,C#,考虑C语言中的以下代码# 现在根据我的理解,t和ob变量都包含TestClass对象的引用值。但是为什么t能够访问属性而ob不能呢?因为C#是一种强类型语言,即使TestClass是一个对象(因为每个类都是一个对象),它也是一个特定的对象 对象是.net中最基本的引用类型。 对象只有每个引用类型都应该具有的最常见的属性和方法。 默认情况下,每个引用类型都继承一个对象,甚至TestClass。想象一下这样的情景: class TestClass : object { public int

考虑C语言中的以下代码#

现在根据我的理解,t和ob变量都包含TestClass对象的引用值。但是为什么t能够访问属性而ob不能呢?

因为C#是一种强类型语言,即使TestClass是一个对象(因为每个类都是一个对象),它也是一个特定的对象

对象是.net中最基本的引用类型。
对象只有每个引用类型都应该具有的最常见的属性和方法。
默认情况下,每个引用类型都继承一个对象,甚至TestClass。想象一下这样的情景:

class TestClass : object
{
    public int Int { get; set; }
    public string Str { get; set; }
}
顺便说一句,你可以做这些事情(如果你真的坚持):


对象是TestClass的超类,需要显式转换为TestClass,然后才能访问任何TestClass特定的成员或方法。

C中的所有类#在您的情况下继承自类

object ob = new TestClass();

ob对象被视为对象类的实例(超类的实例),因此它无法访问类的属性
TestClass
(子类)

,为了能够使用属性,您应该将对象强制转换到相关类:

class TestClass
{
    public int Int { get; set; }
    public string Str { get; set; }
}

TestClass t = new TestClass();
object ob = new TestClass();

Console.WriteLine(((TestClass)ob).Str );
您可以在此处找到有关类型转换的更多信息:


我想这是因为编译时和运行时之间的差异<代码>对象将仅在应用程序的运行时铸造为
TestClass
,而在编译时它仍然是对象。这意味着编译时只有
object
属性可用,因为转换到
TestClass
实际上还没有发生

编译器根据变量的类型而不是变量包含的类型来确定变量上可用的方法和字段。为了确定一个变量实际包含的内容,编译器必须做一些在一般情况下被证明是不确定的(即不可能的),在更具体的情况下至少相当困难的事情


这是记住编译时和运行时之间差异的好时机。编译时的事情发生在编译器处理代码并生成程序集时。运行时的事情发生在程序实际运行时。在编译时,编译器不知道包含哪些变量(必须运行程序才能实现)。它只能对变量可能包含的内容进行推理,因此它不允许您根据变量可能包含或不包含的内容来指定行为。其他语言通过根本不检查类型并将确定要调用哪个函数或访问哪个字段的过程推迟到运行时,就可以解决这个问题。C#不是这样一种语言(动态变量除外)。

您有效地将C#中的所有对象的根类进行了升级。向上投射时,会限制特征,这在协方差和逆方差中是意料之中的

想象

AbstractCar (has turnOn turnOff)
SlowCar (has turnOn turnOff)
FastCar (has turnOn turnOff turboBoost)
如果你有代码说

AbstractCar myCar = SomeFunctionThatCreatesACar();
如果不使用反射,您如何判断返回的汽车是慢车还是快车

所以如果你能在AbstractCar上使用.turboBoost,你就有机会在一辆不起作用的慢车上调用它

你可以安全地使用开关,因为它们是汽车的一部分

如果您愿意,您可以使用带有反光格子的向下投射

if (myCar is FastCar) 
{
   ((FastCar)myCar).turboBoost();
}

但这并不是一个好的实践,因为它打破了“告诉,不要问”的原则。

简短的回答是:
ob
是object类型的,尽管它持有对
TestClass
对象的引用,但在编译时它无法知道关联的成员

是.Net层次结构中所有类的基类

支持.NET Framework类层次结构中的所有类,并且 为派生类提供低级服务。这是终极的 .NET Framework中所有类的基类;这是问题的根源 类型层次结构

但是记住

由于
System.Object
是所有类的基类,因此以下赋值有效

object ob = new TestClass();
由于继承,基类对象可以保存派生类的引用,但它不知道子成员
ob
的视图将仅限于其成员

你可以看到


另一方面,
TestClass
System.Object
的子类(隐式)。它将访问基类成员,如
GetHashCode
Equals
GetType
ToString
等,

ob
不知道它是
TestClass
。它认为它只是一个物体。为什么它总是必须是汽车或动物
if (myCar is FastCar) 
{
   ((FastCar)myCar).turboBoost();
}
object ob = new TestClass();