C#支持值类型和引用类型,但它们都是对象吗?

时间:2022-12-21 04:16:17

I know C# has both value and reference types, but how can you do a this:

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

int age = 100;

string blah = age.ToString();

If age is a value type, how does it have a ToString method on it? Does it get converted to an object ONLY when required internally then?

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

9 个解决方案

#1


You want to look up boxing/unboxing.

你想查找装箱/拆箱。

Boxing

#2


If age is a value type, how does it have a ToString method on it?

如果age是一个值类型,它有一个ToString方法吗?

Value types are allowed to have methods on them. Why wouldn't they? A method "on a type" is just a hunk of code that happens to be associated with a particular type; why do you believe that it matters whether that type is classified as a "reference type" or "value type"?

允许值类型具有方法。他们为什么不呢? “在类型上”的方法只是恰好与特定类型相关联的一大块代码;你为什么认为这种类型被归类为“参考类型”还是“价值类型”?

That's not a rhetorical question. I am interested in learning about what intuitions people have about code, particularly when those intuitions are incorrect. By understanding what people get wrong intuitively, we can try to come up with better abstractions that are more intuitive.

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

Does it get converted to an object ONLY when required internally then?

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

What exactly do you mean by "converted to an object"? Do you mean "boxed"?

“转换为对象”究竟是什么意思?你的意思是“盒装”?

There are many situations in which a value type must be boxed. Some of them are straightforward -- like when you cast a value type to object or an interface. Some of them are obscure. (There are bizarre situations in generic methods where we must box and unbox things in ways you might not expect.)

在许多情况下,必须将值类型装箱。其中一些很简单 - 就像将值类型转换为对象或接口时一样。其中一些是模糊的。 (在通用方法中有一些奇怪的情况,我们必须以你可能没想到的方式装箱和拆箱。)

In this particular situation there is no boxing. Calling a method directly implemented on a value type simply calls that hunk of code. There's no need to treat the thing as "object"; the hunk of code we're calling knows the type of the thing.

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

#3


System.Int32 inherits System.ValueType which inherits System.Object.

System.Int32继承继承System.Object的System.ValueType。

All class, struct, enum, array, nullable and delegate types eventually derive from object. All interface types and type parameter types are implicitly convertible to object. And all pointer types neither derive from nor are convertible to object

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

#4


All Framework objects inherit from System.Object (though it is possible to declare a type in MSIL which doesn't).

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

The object.ToString() method is a virtual method.

object.ToString()方法是一个虚方法。

The special rule for value types which attempt to call a method from System.Object is this:

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

If the value type has overridden the method (as int and all numeric types do with ToString()) then the value type is not boxed ("converted" or "wrapped" to object), but the implementation method is called directly.

如果值类型已重写方法(因为int和所有数字类型都使用ToString()),则值类型不会被装箱(“转换”或“包装”到对象),但直接调用实现方法。

If the value type did not provide an implementation for such method (for example, a custom struct), the value type is boxed, and the base implemented mathod is called.

如果值类型未提供此类方法的实现(例如,自定义结构),则将值类型装箱,并调用基本实现的mathod。

As for details about boxing/unboxing, there's plenty of information in msdn.

至于装箱/拆箱的细节,msdn中有很多信息。

#5


All types (reference and value) inherit from Object. (Although, like others have said it is possible to define one that doesn't, but not in C#, you have to do it in MSIL)

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

This means that any value type will still inherit methods from the base object. In order for a value type to call a method on the base Object type it must first be boxed so it can be treated as a reference type (boxing is the process of taking a value type and shoving it into a reference type shaped box so it behaves like a reference type). However in this specific case Int32 implements it's own version of ToString (as do most of the common numeric value types) which is just a normal methods on the value type itself, so it doesn't have to be boxed to call it.

这意味着任何值类型仍将继承基础对象的方法。为了使值类型在基础对象类型上调用方法,必须首先对其进行装箱,以便将其视为引用类型(装箱是获取值类型并将其推入引用类型形状框的过程,以便它表现得像参考类型)。但是在这个特定的情况下,Int32实现了它自己的ToString版本(就像大多数常见的数值类型一样),它只是值类型本身的常规方法,因此不必将其装箱来调用它。

Value types, can have methods and properties just like reference types. The limitations are that structs (C#'s value types) don't support inheritance (except from Object) or finalizers.

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

There is a good article on the differences between value and reference types here .

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

#6


Comparing "Value Type" vs "Reference Type" doesn't say anything about whether the type is or is not an object. All it tells is you is the semantics of the type: things like how it's passed to functions, whether you need to use 'new' to instantiate it, and whether it's stored on the stack or the heap. Even that last one is just an implementation detail.

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

#7


Perhaps more of an understanding of the OO calling convention is needed.

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

When an object is created, it doesn't actually copy the code for ToString, behind the scenes your object call is translated from

创建对象时,它实际上不会复制ToString的代码,而是在后台转换对象调用

target.ToString ();

to something logically like:

到逻辑上的东西:

ToString (target);

So there's only one copy of function code (per polymorphic instance) and an object pointer is passed in when a method is called.

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

#8


all of the answers are mostly correct but i feel like the method belongs to system.object and system.valuetype and system.Int32 are derived from it .so when you create an instence of it it will show the methods of the base class .

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

#9


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.

盒装值类型继承自object,但它们具有引用语义而不是值语义。未装箱的值类型不是对象,但在值类型和对象之间存在隐式表示更改转换。接口类型不从Object继承,但在接口类型和Object的变量/参数/字段之间存在隐式表示保留转换。请注意,泛型上的接口约束不会使泛型类型成为接口类型。如果泛型类型恰好是值类型,则从泛型类型到Object或接口类型的转换将是表示保留转换,即使它实现了转换其类型的接口。

#1


You want to look up boxing/unboxing.

你想查找装箱/拆箱。

Boxing

#2


If age is a value type, how does it have a ToString method on it?

如果age是一个值类型,它有一个ToString方法吗?

Value types are allowed to have methods on them. Why wouldn't they? A method "on a type" is just a hunk of code that happens to be associated with a particular type; why do you believe that it matters whether that type is classified as a "reference type" or "value type"?

允许值类型具有方法。他们为什么不呢? “在类型上”的方法只是恰好与特定类型相关联的一大块代码;你为什么认为这种类型被归类为“参考类型”还是“价值类型”?

That's not a rhetorical question. I am interested in learning about what intuitions people have about code, particularly when those intuitions are incorrect. By understanding what people get wrong intuitively, we can try to come up with better abstractions that are more intuitive.

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

Does it get converted to an object ONLY when required internally then?

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

What exactly do you mean by "converted to an object"? Do you mean "boxed"?

“转换为对象”究竟是什么意思?你的意思是“盒装”?

There are many situations in which a value type must be boxed. Some of them are straightforward -- like when you cast a value type to object or an interface. Some of them are obscure. (There are bizarre situations in generic methods where we must box and unbox things in ways you might not expect.)

在许多情况下,必须将值类型装箱。其中一些很简单 - 就像将值类型转换为对象或接口时一样。其中一些是模糊的。 (在通用方法中有一些奇怪的情况,我们必须以你可能没想到的方式装箱和拆箱。)

In this particular situation there is no boxing. Calling a method directly implemented on a value type simply calls that hunk of code. There's no need to treat the thing as "object"; the hunk of code we're calling knows the type of the thing.

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

#3


System.Int32 inherits System.ValueType which inherits System.Object.

System.Int32继承继承System.Object的System.ValueType。

All class, struct, enum, array, nullable and delegate types eventually derive from object. All interface types and type parameter types are implicitly convertible to object. And all pointer types neither derive from nor are convertible to object

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

#4


All Framework objects inherit from System.Object (though it is possible to declare a type in MSIL which doesn't).

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

The object.ToString() method is a virtual method.

object.ToString()方法是一个虚方法。

The special rule for value types which attempt to call a method from System.Object is this:

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

If the value type has overridden the method (as int and all numeric types do with ToString()) then the value type is not boxed ("converted" or "wrapped" to object), but the implementation method is called directly.

如果值类型已重写方法(因为int和所有数字类型都使用ToString()),则值类型不会被装箱(“转换”或“包装”到对象),但直接调用实现方法。

If the value type did not provide an implementation for such method (for example, a custom struct), the value type is boxed, and the base implemented mathod is called.

如果值类型未提供此类方法的实现(例如,自定义结构),则将值类型装箱,并调用基本实现的mathod。

As for details about boxing/unboxing, there's plenty of information in msdn.

至于装箱/拆箱的细节,msdn中有很多信息。

#5


All types (reference and value) inherit from Object. (Although, like others have said it is possible to define one that doesn't, but not in C#, you have to do it in MSIL)

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

This means that any value type will still inherit methods from the base object. In order for a value type to call a method on the base Object type it must first be boxed so it can be treated as a reference type (boxing is the process of taking a value type and shoving it into a reference type shaped box so it behaves like a reference type). However in this specific case Int32 implements it's own version of ToString (as do most of the common numeric value types) which is just a normal methods on the value type itself, so it doesn't have to be boxed to call it.

这意味着任何值类型仍将继承基础对象的方法。为了使值类型在基础对象类型上调用方法,必须首先对其进行装箱,以便将其视为引用类型(装箱是获取值类型并将其推入引用类型形状框的过程,以便它表现得像参考类型)。但是在这个特定的情况下,Int32实现了它自己的ToString版本(就像大多数常见的数值类型一样),它只是值类型本身的常规方法,因此不必将其装箱来调用它。

Value types, can have methods and properties just like reference types. The limitations are that structs (C#'s value types) don't support inheritance (except from Object) or finalizers.

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

There is a good article on the differences between value and reference types here .

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

#6


Comparing "Value Type" vs "Reference Type" doesn't say anything about whether the type is or is not an object. All it tells is you is the semantics of the type: things like how it's passed to functions, whether you need to use 'new' to instantiate it, and whether it's stored on the stack or the heap. Even that last one is just an implementation detail.

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

#7


Perhaps more of an understanding of the OO calling convention is needed.

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

When an object is created, it doesn't actually copy the code for ToString, behind the scenes your object call is translated from

创建对象时,它实际上不会复制ToString的代码,而是在后台转换对象调用

target.ToString ();

to something logically like:

到逻辑上的东西:

ToString (target);

So there's only one copy of function code (per polymorphic instance) and an object pointer is passed in when a method is called.

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

#8


all of the answers are mostly correct but i feel like the method belongs to system.object and system.valuetype and system.Int32 are derived from it .so when you create an instence of it it will show the methods of the base class .

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

#9


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.

盒装值类型继承自object,但它们具有引用语义而不是值语义。未装箱的值类型不是对象,但在值类型和对象之间存在隐式表示更改转换。接口类型不从Object继承,但在接口类型和Object的变量/参数/字段之间存在隐式表示保留转换。请注意,泛型上的接口约束不会使泛型类型成为接口类型。如果泛型类型恰好是值类型,则从泛型类型到Object或接口类型的转换将是表示保留转换,即使它实现了转换其类型的接口。