请帮助我们解决“几乎”一切都是对象的争议(an answer to Stack Overflow question As a novice, is there anything I should beware of before learning C#?)。我认为就是这种情况,因为Visual Studio中的所有内容至少都显示为结构体。请张贴参考文献,以免它成为“现代傻瓜”(This American Life)。
请注意,这个问题涉及C#,不一定是.NET,以及它如何处理引擎盖下的数据(显然它都是1和0)。
以下是“一切都是对象”的评论:
对象的定义:“对象”作为类System.Object的继承者与“对象”作为类型与“对象”作为引用类型的实例。“
答案 0 :(得分:79)
这里的问题是,这实际上是两个问题 - 一个问题是关于继承,在这种情况下答案是“几乎所有”,另一个是关于引用类型与值类型/内存/拳击,这种情况下答案是“不”。
<强>继承:强>
在C#中,以下情况属实:
System.Object
。 System.Object
。System.Object
派生的。它们都可以转换为System.Object
,但接口只派生自其他接口类型,System.Object
不是接口类型。 System.Object
,也不能直接转换为System.Object
。System.Object
派生的。类型参数类型不是从任何东西派生的;类型参数被约束为从有效基类派生,但它们本身不是从任何东西“派生”的。来自the MSDN entry for System.Object:
支持.NET中的所有类 框架类层次结构并提供 派生类的低级服务。 这是所有人的终极基础 .NET Framework中的类;它是 类型层次结构的根。
语言通常不需要 用于声明继承的类 对象,因为继承是 隐式的。
因为.NET中的所有类 框架派生自Object, Object中定义的每个方法 class在所有对象中都可用 系统。派生类可以做也可以做 覆盖其中一些方法。
因此,并非C#中的每个类型都来自System.Object
。即使对于那些类型,您仍需要注意reference types和value types之间的区别,因为它们的处理方式截然不同。
<强>拳击:强>
虽然值类型从System.Object
继承,但它们在内存中与引用类型的区别对待,并且它们在代码中通过方法传递的语义也不同。实际上,值类型不会被视为Object(引用类型),直到您通过将其作为引用类型明确指示应用程序执行此操作。请参阅more information about boxing in C# here。
答案 1 :(得分:29)
派对有点晚了,但我在搜索结果中遇到了这个问题,并认为下面的链接有助于后代:
Eric Lippert discusses this very thoroughly,有更好的(合格的)声明:
纠正这个神话的方法是简单地将“derives from”替换为“is convertible to”,并忽略指针类型:C#中的每个非指针类型都可以转换为object。
它的要点,如果你讨厌从编写编程语言的人那里阅读有说明性的解释,那就是(指针除外),诸如Interface或泛型参数类型声明(“T”)之类的东西不是对象,而是保证在运行时可以作为对象处理,因为它们有一个明确的实例,它将是一个Object。其他类型(类型,枚举,代理,类等)都是对象。包括值类型,可以像其他答案一样讨论对象。
答案 2 :(得分:16)
这里的一些人对于面向对象编程中的“对象”有一个奇怪的概念。为了使某些东西成为一个对象,不必须是一个引用类型,或者更一般地说,遵循任何正式的实现。
所有这一切都意味着你可以在面向对象的世界中作为一流的公民进行操作。由于你可以对C#中的值执行此操作(感谢自动装箱),所以一切都确实是一个对象。在某种程度上,这对于函数来说甚至是正确的(但可以说不适用于类)。
这在实践中是否相关是另一个问题,但这是OOP的一个普遍问题,我再次注意到了。没有人清楚OOP的定义(是的,大多数人都认为它与多态性,继承和封装有关,有些人会把“抽象”放在好的方面)。
从使用的角度来看,C#中的每个值都像对象一样处理。那就是说,我喜欢目前接受的答案。它提供了技术上重要的两个方面。
请注意,在其他情况下,例如C ++,其他方面都受到了强调,因为C ++不一定是面向对象的,而且更侧重于低级方面。因此,对象,POD和内置基元之间的区别有时是有意义的(然后有时也是如此)。
答案 3 :(得分:7)
它们都被视为对象,但它们并非都是对象。 Autoboxing引起了混乱。
有关详情,请参阅此处:http://en.wikipedia.org/wiki/Object_type
抽象使人们显然感到困惑。
答案 4 :(得分:6)
您将对象与值或引用混淆。基本上,一切都是一个对象。 Int是一个对象,但它也是一个值类型。类实例是一个对象,但它也是一个引用类型。
方法不是对象,也不是属性。只是操作对象。是的,几乎所有东西都继承自对象类。
答案 5 :(得分:6)
我认为值类型不是对象。它们在内存中以不同的方式存储在CLR中 - 值类型存储在堆栈中,对象存储在堆上。您可以将值类型转换为引用类型以使它们像对象一样工作,但CLR将值从堆栈中取出,将其包装在对象中,并将其存储在堆上。这就是当你“装箱”一个变量时会发生的事情。
答案 6 :(得分:5)
在C#中(通常在OOP中)我们有类型(类 - 引用,结构 - 值等)。这些是定义。而“对象”是给定类型的具体实例。
因此,如果我们按字面意思阅读问题,是的,在实例化时,一切都是对象。
混乱很可能始于对所有内容的基类名称的错误选择。在.NET中,这是Object类。
答案 7 :(得分:3)
根据我阅读的所有书籍,C#中的所有内容都是一个对象。
有些是参考其他是值类型。值类型对象继承自类ValueType。他们有不同的行为,但本质上是......对象。
这就是为什么你可以在对象变量中存储Int32以及在.NET中创建的所有内容的原因。
有关详情......请查看以下内容:http://msdn.microsoft.com/en-us/library/s1ax56ch(VS.71).aspx
所有值类型都是隐式派生的 来自Object类。
答案 8 :(得分:3)
来自:Value Types (C# Reference) - MSDN 3.5
所有值类型都是隐式派生的 来自System.ValueType。
来自:Value Type Class - MSDN 3.5
ValueType会覆盖虚拟 来自Object的方法更多 适当的价值实现 类型。
此类继承自ValueType
继承层次结构如下:
结论:一切都是对象
答案 9 :(得分:2)
取决于你所说的“一切”和“是一个对象”。如果你定义这两个术语,答案很简单: - )
例如,在某些语言中, if-block 是一个可以作为值传递的对象,分配给变量等等。在C#中并非如此,因此很明显并非所有内容都是C#中的对象。
答案 10 :(得分:2)
虽然每个人似乎都在关注值类型与引用类型的争论,但是我们忘记了C#中既有引用也没有值的一种类型,它不是从对象派生的,也不能转换为对象:指针。
与值和引用类型不同,指针不能转换为对象。
根据MSDN documentation on C# pointer types,
指针类型不会继承 对象并且不存在转换 指针类型和对象之间。 此外,装箱和拆箱不会 支持指针。但是,你可以 转换不同的指针 类型和指针类型之间 积分类型。
答案 11 :(得分:0)
数字2不是对象。
答案 12 :(得分:0)
C#has被称为统一类型系统。这意味着一切都可以被视为一个对象。但是,在此下面有两种不同的类型:值类型和引用类型。可以通过装箱机制将值类型视为对象。这意味着创建了一个对象,表示所讨论的值类型的值。
答案 13 :(得分:0)
考虑到问题是指OOP意义上的Object,答案是:
从技术的角度来看,答案是:否
从教条主义的角度来看,答案是:是
说明:
技术上的值类型(基元或结构)不是对象,除非是“盒装”形式,而是因为.Net通过装箱/拆箱行为将值类型无缝转换为其对象(创建一个类实例,值和派生自Object),这意味着值类型可以被视为对象和简单值。
因此,值类型本质上是双重的,它们表现为值和对象。 .Net中的值是需要的对象,在其他情况下它们不是对象。
考虑到技术方面的正确答案是“.Net中的所有内容好像它是一个对象”。
教条的回答是“一切都是对象”。
答案 14 :(得分:0)
这是对两个世界的讨论:语言和记忆。
对我来说语言就像一个抽象层,术语对象属于这个抽象层次。我不会在记忆组织方面谈论对象,如果你在谈论记忆时使用“对象”术语,你实际上是从不同的抽象层借用这个术语。因此,你不应该忘记它的来源。
如果我们谈论C#,我不会理解为什么有人会使用内存组织作为参数。当然,如果我要回答这个问题,我会说“是的,在C#中,一切都是一个对象,但你也应该知道,根据......它可能会有所不同......”
这可能会引发一个有趣的争论,但也可能会对某些人说: 在类似的讨论中,可以说实际上没有面向对象的编程,只有程序编程。你的CPU是否了解对象? 更好的是,实际上没有软件,只有不同的硬件状态:)
我的观点是,某些术语不会转换为其他抽象层,您应该将讨论粘贴到它所属的位置(在这种情况下,它是一种语言,而不是内存)。
即便是这个问题的作者说: “请注意,这个问题反映了C#不一定是.NET以及它如何处理引擎盖下的数据(显然它都是1和0)。”
答案 15 :(得分:0)
解决语义问题,为什么当我们已经有一个非常好的,明确的术语 - >&gt;时,为什么重载单词“object”以便它意味着“引用类型”。 “引用类型”,以及何时,通过以这种方式重载单词“Object”,我们创建了这个线程演示的混淆......即,所有类型(包括值类型)继承定义的实现之间的不匹配在类型“System.Object”中。显然,这至多是不必要的,最糟糕的是非常混乱。即使MS文档有时在这个问题上令人困惑这一事实也不是宣传混淆的借口。
更简单,更清晰的是,只需定义和使用术语“对象”来表示任何类型,值或引用的实例,并使用短语“引用类型”来描述使用指针变量并具有它们的类型状态存储在Heap ...
答案 16 :(得分:0)
值类型不是对象,它们遵循不同的复制语义,不同的传递语义,并且必须包装在类(Object)中才能被视为对象。
编辑:我认为这个论点有点模糊,因为你必须限定'对象'的含义。对象只是从Object继承的东西,还是服从Object的语义?或者我们是在谈论对象的最一般定义,它是什么可以包含对该数据的数据和操作?
答案 17 :(得分:-1)
答案如此之多的原因之一是这个问题非常不精确。 “一切”是什么意思?这真的意味着每个C#语言元素吗?那么答案显然是“否”:运算符不是对象,“ using”关键字不是对象,注释不是对象,等等。
但是,如果不是这个意思,那是什么意思呢?也许“除了那些显然不是阶级的东西之外的一切”?这显然无济于事,因为不同的人对“显而易见的”有不同的看法。尽管如此,大多数答案似乎都遵循这种自以为是的解释。
另一个混乱的根源是“对象”一词。什么是物体?这个术语没有唯一的通用定义,并且不同的人似乎以不同的方式使用它。 C#语言中唯一的正式定义是System.Object类型的定义以及从中派生的其他类型,而不是。该文档随时可用,因此就不多说了。