C# 为什么f(double)比f(long,int=0)更适合f(long)?

C# 为什么f(double)比f(long,int=0)更适合f(long)?,c#,C#,我的一位同事发现这种情况很奇怪。我在这里发布了一个简单的例子: using System; namespace Test { public class F { public void f(double d) { Console.WriteLine("public void F.f(double d)"); } public virtual void f(long l, int q = 0) { Console.WriteLine("public

我的一位同事发现这种情况很奇怪。我在这里发布了一个简单的例子:

using System;

namespace Test
{
    public class F
    {
        public void f(double d) { Console.WriteLine("public void F.f(double d)"); }
        public virtual void f(long l, int q = 0) { Console.WriteLine("public virtual void F.f(long l, int q = 0)"); }
    }

    public class FDerived : F
    {
        public override void f(long l, int q) { Console.WriteLine("public override FDerived.f(long l, int q)"); }
        public void g() { f(2L); }
    }

    public class G : FDerived
    {
        public void h1() { F fd = new FDerived(); fd.f(2L); }
        public void h2() { FDerived fd = new FDerived(); fd.f(2L); }
    }

    class Program
    {
        static void Main(string[] args)
        {
            new FDerived().g();
            new G().h1();
            new G().h2();
            Console.ReadLine();
        }
    }
}
public class F
{
    public virtual void f(long l, int q = 0) { Console.WriteLine("public virtual void F.f(long l, int q = 0)"); }
}

public class FDerived : F
{
    public override void f(long l, int q) { Console.WriteLine("public override FDerived.f(long l, int q)"); }
}

// Doesn't compile: No overload for method 'f' takes 1 arguments
new FDerived().f(5L);
示例的输出为:

public void F.f(double d)
public override FDerived.f(long l, int q)
public void F.f(double d)
我不明白这有什么意义

为什么f(double)比f(long,int=0)更适合f(long)?为什么它取决于“fd”的类型

我这里没有C#规范,但是可选参数值不会被重写的方法继承

尝试在导出的
f中更改

public override void f(long l, int q)

它将按预期工作

请注意,这可以在一个简单的示例中显示:

using System;

namespace Test
{
    public class F
    {
        public void f(double d) { Console.WriteLine("public void F.f(double d)"); }
        public virtual void f(long l, int q = 0) { Console.WriteLine("public virtual void F.f(long l, int q = 0)"); }
    }

    public class FDerived : F
    {
        public override void f(long l, int q) { Console.WriteLine("public override FDerived.f(long l, int q)"); }
        public void g() { f(2L); }
    }

    public class G : FDerived
    {
        public void h1() { F fd = new FDerived(); fd.f(2L); }
        public void h2() { FDerived fd = new FDerived(); fd.f(2L); }
    }

    class Program
    {
        static void Main(string[] args)
        {
            new FDerived().g();
            new G().h1();
            new G().h2();
            Console.ReadLine();
        }
    }
}
public class F
{
    public virtual void f(long l, int q = 0) { Console.WriteLine("public virtual void F.f(long l, int q = 0)"); }
}

public class FDerived : F
{
    public override void f(long l, int q) { Console.WriteLine("public override FDerived.f(long l, int q)"); }
}

// Doesn't compile: No overload for method 'f' takes 1 arguments
new FDerived().f(5L);
显然,这确实是:

new F().f(5L);
即使是这个:

F obj = new FDerived();
obj.f(5L);

(这个将输出
公共覆盖FDerived.f(long l,int q)

提示:除非您真的必须……,否则不要使用继承:)可能是一个复制品。请注意,如果您在
FDerived
中定义了
public override void f(long l,int q=0)
,它将按照您的需要工作。对watch的回应是Marc GravellAnd重申了关于这个重复问题的第一条评论:可选参数是一种代码气味。避免它们甚至比避免继承还要多。