我知道 C# 既有值类型又有引用类型,但你怎么能这样做:
int age = 100;
string blah = age.ToString();
如果 age 是一个值类型,它怎么会有一个 ToString 方法呢?它是否仅在内部需要时才转换为对象?
我知道 C# 既有值类型又有引用类型,但你怎么能这样做:
int age = 100;
string blah = age.ToString();
如果 age 是一个值类型,它怎么会有一个 ToString 方法呢?它是否仅在内部需要时才转换为对象?
如果 age 是一个值类型,它怎么会有一个 ToString 方法呢?
允许值类型对它们有方法。他们为什么不呢?“一种类型”的方法只是碰巧与特定类型相关联的一大块代码;为什么您认为该类型被归类为“引用类型”或“值类型”很重要?
这不是一个修辞问题。我有兴趣了解人们对代码的直觉,尤其是当这些直觉不正确时。通过直观地理解人们犯了什么错误,我们可以尝试提出更直观的更好的抽象。
它是否仅在内部需要时才转换为对象?
“转换为对象”到底是什么意思?你是说“盒装”吗?
在许多情况下,值类型必须被装箱。其中一些是直截了当的——比如当您将值类型转换为对象或接口时。其中一些是模糊的。(在泛型方法中有一些奇怪的情况,我们必须以您可能没想到的方式对事物进行装箱和拆箱。)
在这种特殊情况下,没有拳击。调用直接在值类型上实现的方法只会调用大量代码。没有必要将事物视为“对象”;我们调用的代码块知道事物的类型。
System.Int32
继承System.ValueType
哪个继承System.Object
。
所有类、结构、枚举、数组、可为空和委托类型最终都派生自对象。所有接口类型和类型参数类型都可以隐式转换为对象。并且所有指针类型既不派生自对象也不能转换为对象
您想查找装箱/拆箱。
所有 Framework 对象都继承自 System.Object(尽管可以在 MSIL 中声明一个没有的类型)。
该object.ToString()
方法是虚拟方法。
尝试从中调用方法的值类型的特殊规则System.Object
是:
如果值类型覆盖了方法(如 int 和所有数字类型都使用ToString()
),则值类型不会被装箱(“转换”或“包装”为对象),而是直接调用实现方法。
如果值类型没有提供此类方法的实现(例如,自定义struct
),则值类型被装箱,并调用基本实现的方法。
至于装箱/拆箱的详细信息,msdn 里面有很多资料。
所有类型(引用和值)都继承自 Object。(虽然,就像其他人说的那样,可以定义一个没有,但不是在 C# 中,你必须在 MSIL 中做)
这意味着任何值类型仍将继承基础对象的方法。为了让值类型调用基本 Object 类型上的方法,必须首先将其装箱,以便将其视为引用类型(装箱是获取值类型并将其推入引用类型形状的框的过程,因此它行为类似于引用类型)。然而,在这种特定情况下,Int32 实现了它自己的 ToString 版本(与大多数常见的数值类型一样),这只是值类型本身的普通方法,因此不必将其装箱即可调用它。
值类型,可以像引用类型一样具有方法和属性。限制是结构(C# 的值类型)不支持继承(从 Object 除外)或终结器。
这里有一篇关于值和引用类型之间差异的好文章。
比较“值类型”与“引用类型”并没有说明类型是否是对象。它告诉你的是类型的语义:比如它是如何传递给函数的,你是否需要使用'new'来实例化它,以及它是存储在堆栈上还是堆上。即使最后一个也只是一个实现细节。
也许需要更多地了解 OO 调用约定。
创建对象时,它实际上并没有复制 ToString 的代码,在幕后您的对象调用是从
目标.ToString();
逻辑上类似于:
ToString(目标);
所以只有一个函数代码副本(每个多态实例),并且在调用方法时传入一个对象指针。
所有的答案大多是正确的,但我觉得该方法属于 system.object 和 system.valuetype 和 system.Int32 是从它派生的。所以当你创建它的实例时,它会显示基类的方法。
Boxed value types inherit from object, but they have reference semantics rather than value semantics. Unboxed value types are not objects, but there exists an implicit representation-changing conversion between value types and Object. Interfaces types do not inherit from Object, but there exists an implicit representation-preserving conversion between variables/parameters/fields of interface type and Object. Note that an interface constraint on a generic is not make the generic type an interface type. A conversion from a generic type to either Object or an interface type will be a representation-preserving conversion if the generic type happens to be a value type, even if it implements the interfaces to whose type is is converted.