c#不根据参数类型(继承)选择我想要的函数

c#不根据参数类型(继承)选择我想要的函数,c#,inheritance,types,parameters,C#,Inheritance,Types,Parameters,我不确定如何解释这一点,所以我将展示我的示例并详细说明 using System; namespace Demo { static class Program { static void Main() { var test = new ExampleClass(new Bar()); Console.WriteLine(test); } } class Examp

我不确定如何解释这一点,所以我将展示我的示例并详细说明

using System;

namespace Demo
{
    static class Program
    {
        static void Main()
        {
            var test = new ExampleClass(new Bar());

            Console.WriteLine(test);
        }
    }

    class ExampleClass {
        public Foo _foo;

        public ExampleClass(Bar bar)
        {
            _foo = bar;
        }

        public override String ToString() {
            return print(_foo);
        }

        String print(Bar bar) {
            return bar.Name;
        }

        String print(Foo foo) {
            return foo.ToString();
        }
    }

    class Bar : Foo
    {
        public String Name;
    }

    class Foo
    { }
}
好吧,这不起作用

虽然我可以在声明中看到
\u foo
的类型是
foo
,但它也可以是
Bar
,因为它继承自
foo

我的问题是:

为什么编译器看不到
\u foo
的实际类型

如果类型是
Foo
的派生类,为什么总是执行
print(Foo)

已编辑

编辑了我的示例代码,因为它仍然包含在我的大部分原始代码中


感谢Anthony Pegram提供的示例。

我尝试了这个方法,但是如果类SyntaxNode派生自类BaseClassExtension,那么它会像预期的那样工作-因此很难从您向我们展示的代码中看出问题所在

正如我所期望的那样:

using System;

namespace Demo
{
    static class Program
    {
        static void Main()
        {
            var test = new myNode();

            Console.WriteLine(test);
        }
    }

    class myNode
    {
        public SyntaxNode originalNode = new SyntaxNode{Name = "SyntaxNode"};

        public override string ToString()
        {
            return print(originalNode); // This calls print(BaseClassExtention Class)
        }

        string print(BaseClassExtention Class) // <= This gets called.
        {
            return Class.Name;
        }

        string print(BaseClass b)
        {
            return b.ToString();
        }
    }

    class BaseClass
    {}

    class BaseClassExtention : BaseClass
    {
        public string Name { get; set; }
    }

    class SyntaxNode: BaseClassExtention
    {

    }
}
使用系统;
名称空间演示
{
静态类程序
{
静态void Main()
{
var test=newmynode();
控制台写入线(测试);
}
}
类myNode
{
public SyntaxNode originalNode=新的SyntaxNode{Name=“SyntaxNode”};
公共重写字符串ToString()
{
返回print(originalNode);//这调用print(baseclassextension类)
}

字符串打印(BaseClassExtension类)//您的代码并不能很好地说明您的问题,因为您引入了类型为
SyntaxNode
的字段,但没有显示它与
BaseClass/BaseClassExtension
类型层次结构的关系。但是,在给定可理解的类型时,仍然可以回答一些问题

我的问题是:.net运行时为什么看不到原始节点的实际类型?为什么它总是打印(BaseClass),即使类型是BaseClasseExtension

NET运行时不是决定使用哪个重载的对象。这是编译器的一个属性,它使用它所拥有的关于变量类型(或字段、属性)的信息来决定使用哪个重载

一个简单的演示。假设我们有

class Foo { }
class Bar : Foo { }

void Do(Foo foo)
{
     Console.WriteLine("Foo overload");
}

void Do(Bar bar)
{
    Console.WriteLine("Bar overload");
}
然后你就有了密码

Foo foo = new Bar();
Do(foo);
您有一个类型为
Foo
的变量,它恰好引用了类型为
Bar
的对象。编译器在编译时发出代码来调用
Foo
重载,因为它知道这一点,坦白说,这就是您告诉它要做的。(事实上,我们将它实例化到前面的一行中的类型<代码> Bar <代码>中并不是特别相关的。在下一行中,只需考虑<代码> FoO < /代码>可能来自任何地方,我们知道变量<代码> FoO 是“代码> Foo”类型< < /P> 如果您希望在运行时使用更具体的重载,您可以探索双重分派机制,例如。我不特别推荐的另一种方法是通过
dynamic
关键字在运行时确定类型(如果问题已被很好地理解,通常会有更好的替代方法,但有时它是合适的)


运行时动态的语义是您可以在自己的时间内研究的,但这有效地产生了您似乎想要的结果。

看起来您希望根据
原始节点的运行时类型选择
打印
。C正在选择编译时调用的函数-
打印
不是虚拟方法,因此必须在编译时解析调用

你有吗

 public SyntaxNode originalNode;
 string print(BaseClassExtention Class)...
 string print(BaseClass base)...
在编译时,将选择两个打印函数中的一个(基于if
SyntaxNode
BaseClass
还是
BaseClassExtension
)。如果
SyntaxNode
派生自
BaseClassExtension
,则使用
字符串打印(BaseClassExtension类)
版本(因为它比基类
更具体,所以可以同时使用一个和另一个版本)


如果您想根据
originalNode
的运行时类型使行为有所不同,您需要调用
originalNode
的一些虚拟方法作为
print
的一部分,或者手动检查类型并在
print
方法内部执行某些操作。

为什么它不知道?因为这太复杂了,无法理解请显示SyntaxNode的定义。正如@driis所述,您没有定义
SyntaxNode
,它可以是任何东西,给变量起一个与关键字相同的名字,如
base
,这是一个坏主意。您需要将其设为虚拟方法,然后重写它。此代码非常复杂很难阅读,因为您使用的“class”和“base”等词在C#中已经有了含义。您能提供一个简单、易读、完整的文件来说明您的问题吗?
 public SyntaxNode originalNode;
 string print(BaseClassExtention Class)...
 string print(BaseClass base)...