Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/google-sheets/3.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#_Generics_Delegates_Covariance_Contravariance - Fatal编程技术网

C# 哪些重载方法被添加到委托中?

C# 哪些重载方法被添加到委托中?,c#,generics,delegates,covariance,contravariance,C#,Generics,Delegates,Covariance,Contravariance,以下是我在一次测试中看到的一个问题,它提出了一些问题: 给定以下代码: public delegate B func(B b); public class A { public func x; public int i = 2; public A(int i) { this.i = i; x += f; } public virtual C f(A a) { Console.WriteLine("C A.f(A)"); return new C(1); }

以下是我在一次测试中看到的一个问题,它提出了一些问题:

给定以下代码:

public delegate B func(B b);

public class A
{
    public func x;
    public int i = 2;
    public A(int i) { this.i = i; x += f; }
    public virtual C f(A a) { Console.WriteLine("C A.f(A)"); return new C(1); }
    public virtual A f(C c) { Console.WriteLine("A A.f(C)"); return new A(2); }
}

public class B: A{
    public B(int i) : base(i) { x += f; }
    public virtual B f(B b) { Console.WriteLine("B B.f(B)"); return new B(3); }
    public new C f(A a) { Console.WriteLine("C B.f(A)"); return new C(4); } 
}

public class C: B{
    public C(int i) : base(i) { x += f; }
    public new B f(B b) { Console.WriteLine("B C.f(B)"); return new C(5); }
    public override A f(C c) { Console.WriteLine("A C.f(C)"); return new A(6); }
}
主要有以下几点:

static void Main(string[] args)
{
    C c = new C(12);
    A a = c.x(c);
    Console.WriteLine(a.i);
}
  • 输出是什么
  • 如果将委托定义更改为:
    public delegate C func(B)
  • 将委托定义更改为
    public delegate T func(U)时会发生什么情况并将A中的
    x
    更改为
    public func x
  • 官方答复是:

    至#1:

    至#2:

    它不会编译,因为类B和C中添加到
    x
    的方法是根据参数的静态类型选择的。因此,在B类
    B B.f(B)
    中需要添加,但返回类型不匹配;在C类
    B C.f(B)
    中需要添加,但返回类型不匹配

    至#3:

    它打印出与#1相同的答案,因为这两个定义是等效的

    我不明白的是:

  • 如何在
    x+=f行中添加到
    x
    的方法从所有重载选项中选择?是否选择了参数类型与动态类型“this”最接近的重载方法
  • 除非用
    in
    out
    声明,否则泛型委托不是非变量吗?#3的答案有什么意义
  • 是否选择了参数类型与动态类型“this”最接近的重载方法

    否。如果这是真的,那么所有构造函数都会选择相同的方法(
    bc.f(B)
    ),因为它完全匹配并且是最派生的类型。而是使用静态类型的
    this

    这意味着:

  • A
    中,选择
    C A.f(A)
    ,因为它是
    A
    上唯一匹配
    func
    的方法
  • B
    中,选择了
    B B.f(B)
    ,因为这是
    B
    上唯一完全匹配的方法
  • C
    中,选择了
    bc.f(B)
    ,因为它与
    bb.f(B)
    完全匹配,并且以比
    bb.f(B)
    更派生的类型声明
  • 除非用
    in
    out
    声明,否则泛型委托不是非变量吗


    是的,此类委托是不变的,这意味着您不能将
    func
    转换为
    func
    func
    func
    。但它不会改变从方法组转换为委托的规则,这允许类似的转换,无论委托类型是否为泛型。

    那么哪些方法被添加到委托中呢?如果我向类A添加
    公共虚拟C f(B){Console.WriteLine(“C A.f(B)”;返回新的C(2);}
    ,那么它将被添加,而不是
    C A.f(A)
    。请注意,它现在有两个委托类型的方法,新方法与静态类型不匹配。为什么会这样?@Shookie因为它比cf(a a)更匹配。从
    cf(A)
    B func(B)
    ,您必须进行两个更改。从
    cf(B)
    ,只有一个变化。可能值得注意的是,即使是声明使用
    in
    out
    装饰的委托,在涉及
    委托的场景中也无法支持协变或逆变。合并
    @supercat你是什么意思?下面的代码对我来说很好:
    Func fs1=()=>“a”;Func fs2=()=>“b”;Func fo=fs1+fs2;fo().Dump()。这不是你的意思吗?他的意思是这样的:
    Action a1=x=>{};动作a2=x=>{};动作b1=a1;动作b2=a2;var组合=b1+b2。我使用了一个示例,其中委托返回类型为
    void
    ,因为很少组合返回值的委托。
    C A.f(A)
    B B.f(B)
    B C.f(B)
    5