对象 a = new Dog() 与 Dog a = new Dog() 之间的区别

发布于 2024-12-21 20:39:28 字数 219 浏览 1 评论 0 原文

object a = new Dog();

vs

Dog a = new Dog();

在这两种情况下,a.GetType() 都会给出 Dog。 两者都调用相同的构造函数(具有相同的层次结构)。

那你能告诉我这两种说法有什么区别吗?

object a = new Dog();

vs

Dog a = new Dog();

In both cases a.GetType() gives Dog.
Both invoke same constructor (with same hierarchy).

Then can you please tell me the difference between these two statements?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

〗斷ホ乔殘χμё〖 2024-12-28 20:39:28

两者都创建一个 Dog 对象。只有第二个允许您直接调用 Dog 方法或以其他方式将其视为狗,例如,如果您需要将对象作为 Dog 类型的参数(或 Dog 中的某些内容)传递给方法,比简单的对象更具体的层次结构)。

object obj = new Dog(); 
// can only see members declared on object
var type = obj.GetType(); // can do this
Console.WriteLine(obj.ToString()); // also this
obj.Bark(); // Error! Bark is not a member of System.Object

Dog dog = new Dog();
// can do all of the methods declared for Object
dog.Bark(); // can finally use the method defined for Dog

Both create a Dog object. Only the second allows you to directly invoke Dog methods or to otherwise treat it like a dog, such as if you need to pass the object to a method as a parameter of type Dog (or something in the Dog hierarchy that is more specific than simply object).

object obj = new Dog(); 
// can only see members declared on object
var type = obj.GetType(); // can do this
Console.WriteLine(obj.ToString()); // also this
obj.Bark(); // Error! Bark is not a member of System.Object

Dog dog = new Dog();
// can do all of the methods declared for Object
dog.Bark(); // can finally use the method defined for Dog
沫雨熙 2024-12-28 20:39:28

new Dog() 是一个创建新 Dog 实例的表达式。它调用 Dog 类的无参数构造函数。

a 是一个变量:内存中的存储单元,在赋值后保存对 Dog 实例的引用。

区别在于 Dog 变量只能保存对 Dog 实例(或从 Dog 派生的任何类的实例)的引用,而 object 变量可以保存对 object 实例(或派生自 object 的任何类的实例)的引用 - 其中 Dog 类确实如此)。

当您有 Dog 变量时,您可以在引用的实例上调用由 Dog 类(及其基类)定义的任何方法。当您有一个 object 变量时,您只能在实例上调用 object 类的方法。

new Dog() is an expression that creates a new Dog instance. It invokes the parameterless constructor of the Dog class.

a is a variable: a storage cell in memory that holds a reference to the Dog instance after assignment.

The difference is that a Dog variable can only hold a reference to a Dog instance (or an instance of any class that derives from Dog), while an object variable can hold a reference to an object instance (or an instance of any class that derives from object – which the Dog class does).

When you have a Dog variable, you can invoke any method defined by the Dog class (and its base classes) on the referenced instance. When you have an object variable, you can only invoke the methods of the object class on the instance.

爱已欠费 2024-12-28 20:39:28

您的第一行创建一个 object 类型的变量

编译器不会让您将其视为 Dog

Your first line creates a variable of type object.

The compiler won't let you treat that as a Dog.

朕就是辣么酷 2024-12-28 20:39:28

两个语句都包含声明和构造函数调用。构造函数的调用是相同的,因此在两种情况下都会得到一个 Dog。声明是不同的:在第一种情况下,您声明一个 object 类型的变量,它是 Dog 的超类;在第一种情况下,您声明一个 object 类型的变量,它是 Dog 的超类。在第二种情况下,您声明一个 Dog 类型的变量。不同之处在于,在后续代码中,只有当您将变量声明为 Dog 时,才可以在不进行强制转换的情况下调用 Dog 的方法;如果将其声明为object,则需要进行强制转换。

Both statements contain a declaration and a constructor invocation. The invocations of the constructor are identical, therefore you get a Dog in both cases. The declarations are different: in the first case, you declare a variable of type object, a superclass of Dog; in the second case, you declare a variable of type Dog. The difference is that in the subsequent code you can invoke methods of Dog without a cast only when you declare the variable as Dog; if you declare it as object, you would need a cast.

2024-12-28 20:39:28

正如您所提到的,这两个语句都涉及调用 Dog 的默认构造函数;因此,很明显,在这两种情况下都会构造一个 Dog 实例。这意味着两个语句最终都使用相同的实例初始化变量(这是语句中 equals 之后的部分)。

然而,语句还有另一部分:变量声明(这是语句中 equals 之前的部分)。在静态类型语言(例如 C#)中,每个变量(更一般地说,任何表达式)都具有静态类型:

object a = new Dog(); // static type: object / runtime type: Dog
Dog b = new Dog();    // static type: Dog / runtime type: Dog

编译器将不允许您将值分配给它无法证明的变量。变量的静态类型,例如它不允许

Cat c = new Dog(); // unless Dog derives from Cat, which we know isn't true

所有引用类型System.Object隐式派生,将Dog分配给静态类型object的变量就可以了。 您可以将“静态类型”视为对象“声明为”的内容。您始终可以通过阅读源代码来确定某物的静态类型;这就是编译器的工作方式。

然后还有我上面提到的每个变量(表达式)的运行时类型。这在两种情况下都是相同的,因为毕竟在这两种情况下我们都创建了一个Dog您可以将“运行时类型”视为对象的实际某些事物的运行时类型不能仅通过读取源代码来确定;而是需要通过读取源代码来确定。您只能在程序运行时确定它,因此得名。在 C# 中,这是通过调用 GetType 来完成的。

显然,运行时类型是你离不开的; 一切毕竟都必须“是”某种东西。但为什么要费心发明静态类型的概念呢?

您可以将静态类型视为您(程序员)和编译器之间的契约。通过将 b 的静态类型声明为 Dog,您就告诉编译器您不打算使用该变量来存储 Dog 以外的任何内容。代码>.作为回报,编译器承诺不会让您违反既定的目的,并且如果您尝试这样做,则会产生错误。它还会阻止您以任何 Dog 不支持的方式使用 d

考虑一下:

class Dog {
    public void Woof();
}

Dog d = new Dog();
d.Woof(); // OK

object o = new Dog();
o.Woof(); // COMPILER ERROR

最后一行会导致编译器错误,因为它违反了静态类型约定:您告诉编译器 o 可以是从 System.Object 派生的任何内容,但不是全部从中派生的事物有一个方法 Woof。因此,编译器试图通过说“你在那里做什么?我无法证明² o 中的任何内容都可以发出声音!如果它是一只 Cat 怎么办?”来保护你。 。

注释:

1 这并不意味着每个对象都神奇地知道它在所有语言中的“是什么”。在某些情况下(例如在 C++ 中),在创建对象时可能会使用此信息,但随后会“忘记”该信息,以便让编译器更自由地优化代码。如果发生这种情况,该对象仍然某种东西,但你不能戳它并问它“你是什么?”。

² 实际上,在这个简单的例子中就可以证明这一点。但它不会选择使用这些知识,因为遵守静态类型的约定才是重点。

Both statements involve calling the default constructor of Dog as you mention yourself; therefore, it is evident that in both cases a Dog instance is constructed. This means that both statements end up initializing a variable with an identical instance (this is the part of the statement after the equals).

However, the statements also have another part: the declaration of a variable (this is the part of the statement before the equals). In statically typed languages such as C#, every variable -- more generally, any expression -- has a static type:

object a = new Dog(); // static type: object / runtime type: Dog
Dog b = new Dog();    // static type: Dog / runtime type: Dog

The compiler will not allow you to assign a value to a variable that it cannot prove is of the variable's static type, e.g. it would not allow

Cat c = new Dog(); // unless Dog derives from Cat, which we know isn't true

Since all reference types implicitly derive from System.Object, assigning a Dog to a variable of static type object is OK. You can think of "static type" as what the object is "declared as". You can always determine the static type of something just by reading the source code; this is how the compiler does it.

Then there's also the runtime type of each variable (expression), which I mentioned above. This is the same in both cases, because after all in both cases we have created a Dog. You can think of "runtime type" as what the object actually is. The runtime type of something cannot be determined just by reading the source; you only determine it while you program is running, hence the name. In C#, this is done by calling GetType.

It should be obvious that the runtime type is something that you cannot do without¹; everything has to "be" something after all. But why bother with inventing the notion of static type?

You can think of static types as a contract between you (the programmer) and the compiler. By declaring the static type of b to be Dog, you tell the compiler that you do not intend to use that variable for storing anything other than a Dog. The compiler, in return, promises to not let you violate your stated purpose and produces an error if you attempt to do that. It also prevents you from using d in any way that not every kind of Dog should support.

Consider:

class Dog {
    public void Woof();
}

Dog d = new Dog();
d.Woof(); // OK

object o = new Dog();
o.Woof(); // COMPILER ERROR

The last line causes a compiler error because it violates the static typing contract: you told the compiler that o can be anything deriving from System.Object, but not all of the things deriving from that have a method Woof. So the compiler is trying to protect you by saying "What are you doing there? I cannot prove² that whatever is in o can woof! What if it were a Cat?".

Notes:

¹ This does not mean that every object magically knows what it "is" in all languages. In some cases (e.g. in C++) this information might be used when creating an object, but is then "forgotten" in order to allow the compiler more freedom to optimize the code. If this happens the object still is something, but you cannot poke it and ask it "what are you?".

² Actually, in this trivial example it can prove that. But it won't choose to use this knowledge because honoring the contract of the static type is the whole point.

你是年少的欢喜 2024-12-28 20:39:28

当您想要使用多态性并且可以使用在 Dog 中实现的抽象方法时,这非常有用。因此,这样一来object就是Dog,即使是Object也是如此。所以当你想使用多态性时可以使用这种方式。

This is useful when you want to use polymorphism and you can use the abstract method that has implementation in Dog. Therefore, in this way object is Dog, even so is Object. So you may use this manner when you want to use polymorphism.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文