为什么在Main函数中始终需要对象引用来调用子类的方法? [英] Why is object reference is always required in Main function to call a method of child class?

查看:153
本文介绍了为什么在Main函数中始终需要对象引用来调用子类的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道为什么在Main方法中始终需要对象引用来调用子类的方法.

I would like to know why an object reference is always required in the Main method to call a method of the child class.

但是,我们可以通过其他方法中的方法名称直接调用Main方法:

However we can call the Main method directly by a method name from other methods:

using System; 

class MainProgram : Parent_Class 
{
    static void Main(string[] args)
    {
        Project1_Child p = new Project1_Child(); 

        p.PI_add();   //->  Object reference is required     
    }


    public void non_Main_method() 
    {
        PI_add();     //-> No Object reference is required  

    }
}

public class Parent_Class
{


    public void PI_add()
    {

        Console.WriteLine("-------------");

    }

}

这是为什么?

推荐答案

作为其他答案,您需要了解静态方法与实例方法之间的区别.这个答案的重点是使您走上正确术语的道路,并考虑对实例方法的调用.你说:

As the other answer notes, you need to learn the difference between static and instance methods. The point of this answer is to get you on a path of correct terminology and thought about calls to instance methods. You say:

我想知道为什么在Main方法中始终需要对象引用来调用子类的方法.

I would like to know why an object reference is always required in the Main method to call a method of the child class.

让我们分解一下.

  • 呼叫 是一种成员访问权限.也就是说,您在拨打电话时正在访问类型的成员.在这种情况下,您要访问的成员是方法.
  • 每个成员访问权限都有一个接收者.接收者是正在访问其成员的事物.
  • 在旁边:术语接收器"可能看起来令人困惑,为什么接收器"呢?访问类型的成员时,接收到"了什么?这个行话来自这样的想法,即面向对象的编程是关于将消息发送给对象,然后获得答案.当您呼叫x = foo.Bar(123)时,您正在向foo发送一条消息,告知您希望foo执行的计算,并且foo将结果发送回给您,并放入x中.
  • 不要将接收器视为对象引用.在C#中,对象"和引用"都具有非常特定的含义.接收者是 expression ,类型检查器必须验证它是否具有某些属性.在某些情况下,接收器必须是有效的对象引用,但不是全部,正如我们将看到的那样.
  • 有些成员是静态"成员,有些是实例".区别在于:静态成员要求接收者自己命名类型.实例成员要求接收者是该类型的实例.
  • 同样,我们有一个行话问题. 实例"是显而易见的,而静态"则不是.确实没有任何理由要静态"了.从历史上看,通过静态(即编译时间)分析可以确定对静态成员的调用.一些实例成员调用是由运行时动态调度的. VB将静态方法称为共享",这更有意义.它们在类型的实例之间共享".
  • 这里有一个微妙之处,即实例方法的接收者必须是该类型的 valid 实例.如果接收方是引用类型,则它必须在运行时评估为非空引用 .编译器仅检查其类型对编译器是已知的,而不是非null.在C#8中可能会改变!
  • 这里还有另一个微妙之处,即值类型要求接收者不仅是适当类型的 value ,而且是 variable .在某些情况下,C#编译器会在必要时为您创建一个变量,但这又是一个精妙之处,您以后可以学习.
  • 删减"是语言研究中的概念,我们可以从句子中消除"不必要的单词并仍然理解它们.如果我说您有洗碗的地方吗?"您会理解该句子,即使在语法上应该是需要清洗".
  • 现在,我们进入了误解的症结所在. C#可让您在几种特定情况下跳过接收器.
  • 如果您要访问的成员是实例成员,并且您是从实例成员访问它的,那么您可以淘汰接收者,并且C#将假定您的意思是this.
  • 如果您访问的成员是静态成员,并且您可以从其类的任何成员访问它,则可以淘汰接收者,并且在这种情况下,C#会假设您的意思是MainProgram.
  • A call is a kind of member access. That is, you are accessing a member of a type when you make a call. In this case the members you are accessing are methods.
  • Every member access has a receiver. The receiver is the thing whose member is being accessed.
  • Aside: The jargon "receiver" might seem confusing, why "receiver"? What is being "received" when you access a member of a type? This jargon comes from the idea that object oriented programming is about sending messages to objects and then getting answers back. When you call x = foo.Bar(123) you are "sending a message" to foo about what computation you wish foo to perform, and foo sends you the result back to put in x.
  • Do not think of the receiver as an object reference. "Object" and "reference" both have very specific meanings in C#. The receiver is an expression, and the type checker must verify that it has certain properties. In some cases the receiver must be a valid object reference, but not all, as we'll see.
  • Some members are "static" and some are "instance". The difference is: a static member requires that the receiver name the type itself. An instance member requires that the receiver be an instance of the type.
  • Again, we have a jargon problem. "Instance" is obvious, but "static" is not. There really is no good reason for "static" anymore; historically a call to a static member could be determined by static (that is, compile time) analysis. Some instance member calls are dispatched dynamically by the runtime. VB calls static methods "shared" which makes more sense; they are "shared" amongst the instances of a type.
  • There's a subtlety here, in that the receiver of an instance method must be a valid instance of that type. If the receiver is a reference type then it must evaluate to a non-null reference at runtime. The compiler only checks that its type is known to the compiler, not that it is non-null. This may change in C# 8!
  • There's another subtlety here, in that value types require that the receiver be not just a value but a variable of the appropriate type. The C# compiler will in some cases create a variable for you when necessary, but again, this is a subtlety that you can learn about later.
  • "Elision" is the concept in the study of languages that we can "elide" unnecessary words from sentences and still understand them. If I said "Do you have any dishes that need washed?" you'd understand the sentence even though grammatically it ought to be "that need to be washed".
  • Now we come to the crux of the misunderstanding. C# allows you to elide the receiver in several specific cases.
  • If the member you are accessing is an instance member, and you are accessing it from an instance member, then you can elide the receiver, and C# will assume you meant this.
  • If the member you are accessing is a static member, and you are accessing it from any member of its class, then you can elide the receiver and C# will assume you meant, in this case, MainProgram.

这将解释您的观察结果.

This then explains your observations.

  • Main中调用PI_add.那是一个实例成员,所以它需要一个作为实例的接收者.如果您是从实例成员调用,则C#会假定您已删除this.,但您是从静态成员调用的.因此,需要接收器,而将其推倒是错误的.

  • In Main you call PI_add. That's an instance member, so it needs a receiver that is an instance. If you were calling from an instance member then C# would assume that you elided this., but you are calling from a static member. Therefore the receiver is required, and it is an error to elide it.

non_main_method的实例方法中,调用PI_add.这是一个实例方法,因此假定省略的接收器为this.

In non_main_method, an instance method, you call PI_add. It's an instance method, so the elided receiver is assumed to be this.

足够的信息可以使您走上一条更有生产力的道路.当您了解委托和扩展方法时,您会发现这里还有一些关于接收方确切含义以及编译器如何对待它的细微之处.

That's enough information to get you going down a more productive path. When you learn about delegates and extension methods you'll see that there are additional subtleties here about what exactly the receiver is and how the compiler treats it.

这篇关于为什么在Main函数中始终需要对象引用来调用子类的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆