Relation between System.Object class and Structs

2019-02-14 02:24发布

问题:

I know that my question seems dumb but I am confused. I appreciate if someone clarify this for me.

I know that structs, e.g. Int32, are value types and are instantiated on stack while classes are reference types and are instantiated on heap. I also know that all the structs are derived from System.Object type, which is a class. I wonder how this is possible that the supertype, System.Object, is a reference type and the subtype, Int32, is a value type? Where should I look to understand how this works?

回答1:

I know that structs, e.g. Int32, are value types and are instantiated on stack while classes are reference types and are instantiated on heap.

You do not know that, because in order to be classified as knowledge a belief must be true. That belief is certainly not true, though many people believe it.

Value types are sometimes allocated on the stack. References are sometimes allocated on the stack and refer to memory allocated on the heap. Value types are sometimes allocated on the heap. (And of course value types and references may also be allocated in registers which are neither stack nor heap.)

What determines what storage is allocated on the heap and what is allocated on the stack is the known lifetime requirements of the storage, not what kind of thing it is. If a variable is known to be short-lived then it can be allocated on the stack; if it is not known to be short-lived then it must be allocated on the heap.

I also know that all the structs are derived from System.Object type, which is a class. I wonder how this is possible that the supertype, System.Object, is a reference type and the subtype, Int32, is a value type?

I suspect that you don't understand what "inherits from" means in the first place if this is confusing to you. When we say that System.Int32, a value type, inherits from System.Object, a reference type, we mean that all members of Object are also members of Int32. Object has a method "ToString". That's a member of Object. Therefore Int32 also has a method "ToString", because Int32 inherits from Object.

That is all that inheritance means. I suspect that you believe that inheritance means something else, and that whatever that "something" is precludes value types from extending reference types. Whatever belief you have that makes you think that value types cannot inherit from reference types is clearly false, since obviously they do.

I am interested to learn what false things people believe about programming languages; what is it that you think incorrectly is true about the inheritance relationship that would preclude value types from deriving from reference types?

You should read and understand all of these articles:

http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx

http://blogs.msdn.com/b/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx

http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx

http://ericlippert.com/2011/09/19/inheritance-and-representation/

And extra bonus, this one might also be helpful to you:

http://blogs.msdn.com/b/ericlippert/archive/2012/01/16/what-is-the-defining-characteristic-of-a-local-variable.aspx



回答2:

First of all, the distinguishing feature of value types is not where they are stored but how they are passed to methods. Struct's are passed by value; that is a copy of the argument is created and passed. Any changes to the copy within the method does not affect the actual argument (unless they share the same reference) Reference types are passed by reference; that is a pointer to the actual argument is passed.

Yes, structs are derived from ValueType. And ValueType is derived from Object. So, ultimately structs are also derived from Object. (For example, the methods ToString(), ==, Equals(), GetHashCode() and perhaps a few others are defined in Object and hence also available in struct's)

However, the semantics of argument passing are not defined within classes themselves; there is no code within the definition of Object that says "any instances of my subtypes are to be passed by reference" and there is no code within the definition of ValueType that says "any instances of my subtypes are to be passed by value". [Perhaps there is a special attribute but that doesn't count] It is the responsibility of the compiler to honor that. (There is some code somewhere within C# compilers that says "generate code such that descendants of ValueType will be passed by value and others will be passed by reference")

Eric Lippert's blog is a fantastic resource on many issues about C#, and you should read the link @Heinzi gave for further clarifications.



标签: c# clr