5

我知道 C# 既有值类型又有引用类型,但你怎么能这样做:

int age = 100;

string blah = age.ToString();

如果 age 是一个值类型,它怎么会有一个 ToString 方法呢?它是否仅在内部需要时才转换为对象?

4

9 回答 9

11

如果 age 是一个值类型,它怎么会有一个 ToString 方法呢?

允许值类型对它们有方法。他们为什么不呢?“一种类型”的方法只是碰巧与特定类型相关联的一大块代码;为什么您认为该类型被归类为“引用类型”或“值类型”很重要?

这不是一个修辞问题。我有兴趣了解人们对代码的直觉,尤其是当这些直觉不正确时。通过直观地理解人们犯了什么错误,我们可以尝试提出更直观的更好的抽象。

它是否仅在内部需要时才转换为对象?

“转换为对象”到底是什么意思?你是说“盒装”吗?

在许多情况下,值类型必须被装箱。其中一些是直截了当的——比如当您将值类型转换为对象或接口时。其中一些是模糊的。(在泛型方法中有一些奇怪的情况,我们必须以您可能没想到的方式对事物进行装箱和拆箱。)

在这种特殊情况下,没有拳击。调用直接在值类型上实现的方法只会调用大量代码。没有必要将事物视为“对象”;我们调用的代码块知道事物的类型。

于 2009-07-06T16:45:31.803 回答
6

System.Int32继承System.ValueType哪个继承System.Object

所有类、结构、枚举、数组、可为空和委托类型最终都派生自对象。所有接口类型和类型参数类型都可以隐式转换为对象。并且所有指针类型既不派生自对象也不能转换为对象

于 2009-07-06T13:34:45.067 回答
6

您想查找装箱/拆箱。

拳击

于 2009-07-06T13:35:03.990 回答
3

所有 Framework 对象都继承自 System.Object(尽管可以在 MSIL 中声明一个没有的类型)。

object.ToString()方法是虚拟方法。

尝试从中调用方法的值类型的特殊规则System.Object是:

如果值类型覆盖了方法(如 int 和所有数字类型都使用ToString()),则值类型不会被装箱(“转换”或“包装”为对象),而是直接调用实现方法。

如果值类型没有提供此类方法的实现(例如,自定义struct),则值类型被装箱,并调用基本实现的方法。

至于装箱/拆箱的详细信息,msdn 里面有很多资料。

于 2009-07-06T13:42:19.300 回答
3

所有类型(引用和值)都继承自 Object。(虽然,就像其他人说的那样,可以定义一个没有,但不是在 C# 中,你必须在 MSIL 中做)

这意味着任何值类型仍将继承基础对象的方法。为了让值类型调用基本 Object 类型上的方法,必须首先将其装箱,以便将其视为引用类型(装箱是获取值类型并将其推入引用类型形状的框的过程,因此它行为类似于引用类型)。然而,在这种特定情况下,Int32 实现了它自己的 ToString 版本(与大多数常见的数值类型一样),这只是值类型本身的普通方法,因此不必将其装箱即可调用它。

值类型,可以像引用类型一样具有方法和属性。限制是结构(C# 的值类型)不支持继承(从 Object 除外)或终结器。

这里有一篇关于值和引用类型之间差异的好文章。

于 2009-07-06T13:55:14.590 回答
1

比较“值类型”与“引用类型”并没有说明类型是否是对象。它告诉你的是类型的语义:比如它是如何传递给函数的,你是否需要使用'new'来实例化它,以及它是存储在堆栈上还是堆上。即使最后一个也只是一个实现细节

于 2009-07-06T13:40:39.413 回答
1

也许需要更多地了解 OO 调用约定。

创建对象时,它实际上并没有复制 ToString 的代码,在幕后您的对象调用是从

目标.ToString();

逻辑上类似于:

ToString(目标);

所以只有一个函数代码副本(每个多态实例),并且在调用方法时传入一个对象指针。

于 2009-07-06T15:53:00.457 回答
0

所有的答案大多是正确的,但我觉得该方法属于 system.object 和 system.valuetype 和 system.Int32 是从它派生的。所以当你创建它的实例时,它会显示基类的方法。

于 2009-10-02T05:19:28.103 回答
0

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.

于 2011-12-20T02:25:27.853 回答