Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么编译器在父类中查找方法_C#_Asp.net_.net - Fatal编程技术网

C# 为什么编译器在父类中查找方法

C# 为什么编译器在父类中查找方法,c#,asp.net,.net,C#,Asp.net,.net,我遇到错误,parent不包含“Print”的定义,并且找不到接受第一个参数类型为“parent”的扩展方法“Print”(是否缺少using指令或程序集引用?) 这就是多态性的作用。您声明p1,因此: parent p1 = new child(); 因此,您对p1的引用是作为parent的一个实例。该类不包含Print()的定义,因此该行出现错误: p1.Print(); 如果将声明行更改为以下之一: var p1 = new child(); 或 然后,当您作为child的实例访问p

我遇到错误,parent不包含“Print”的定义,并且找不到接受第一个参数类型为“parent”的扩展方法“Print”(是否缺少using指令或程序集引用?)


这就是多态性的作用。您声明
p1
,因此:

parent p1 = new child();
因此,您对
p1
的引用是作为
parent
的一个实例。该类不包含
Print()
的定义,因此该行出现错误:

p1.Print();
如果将声明行更改为以下之一:

var p1 = new child();

然后,当您作为
child
的实例访问
p1
时,错误将消失

或者,您可以在
parent
中声明
Print
,并在
child
中重写它:

public class parent
{
    public virtual void Print() { // do something }
}

public class child : parent
{
    public override void Print() { // do something else }
}

编译器是正确的:
parent
类没有方法
Print
的定义。即使分配给
p1
的对象具有
打印
,编译器也无法从
p1
的声明中知道它,并且不允许使用初始值设定项来计算它

为了帮助编译器执行您希望它执行的操作,您需要执行以下操作之一:

  • parent
    一个虚拟方法
    Print
    ,其签名与
    child
    中的签名相同,并将
    override
    添加到
    child
    中的定义中
  • 声明一个具有
    Print
    方法的接口,并使
    parent
    实现它
  • 声明
    p1
    类型为
    child
  • 在进行呼叫之前,将
    p1
    的显式强制转换添加到
    child
  • 声明
    p1
    类型为
    dynamic

  • 如果采用方法1、2、3或4,C#将能够在编译时检查
    p1
    对象上是否存在
    Print
    。如果采用方法5,编译器将把检查推迟到运行时,此时CLR必须对
    Print
    方法执行额外的搜索,并调用它或抛出运行时错误。

    当我写入父p1=new child()时,我的理解是p1只是一个引用变量,它指向实际的子类对象。所以如果我这么说,那么p1不是父对象,而是子对象……那么为什么它是父类呢method@BhuwanPandey,它指向子实例,但它被引用为父对象。因此,在本例中,您仅限于在父级中声明的方法。理解为什么会出现这种情况会让你理解多态性:)谢谢Dave,但实际上如果我们写child c=new child(),这里是c--它是一个引用变量,在堆栈上分配了内存……现在new child()将实际创建一个对象,并在堆上分配内存……这里,堆栈上的c引用变量指向在堆上创建的子对象。现在,如果我取parent p1=new child(),这里的p1引用变量也将只指向子对象……那么new child()怎么会出现呢将创建一个父对象…………我完全搞糊涂了我对父对象p1=新子对象()感到困惑;p1.Print();父级p2=新父级();p2.Print();非常感谢这真的很有意义…非常好的解释…非常感谢。非常感谢如果您采用方法5,编译器将延迟检查到运行时,此时CLR将不得不对Print方法执行额外的搜索,并调用它或抛出运行时错误…我没有意识到这一点,这真的很好。
    child p1 = new child();
    
    public class parent
    {
        public virtual void Print() { // do something }
    }
    
    public class child : parent
    {
        public override void Print() { // do something else }
    }