为什么这段代码要用 long 替换 float?

Why does this code replace float with long?

我以这段代码为例:

class A<T> {
    public class B : A<long> {
        public void f() {
            Console.WriteLine( typeof(T).ToString());
        }
 
    public class C : A<long>.B { }
    
    } 
}

class Prg5 { static void Main() {
    var c = new A<float>.B.C();
    c.f();
} }

输出:

System.Int64

为什么打印的字体很长?最初传递的 float 类型如何以及在何处被替换?

回答

当您调用 f 时,您处于 A<T>,其中 Tlong 因为 BA<long> 所以 Tlong.

我明白为什么它看起来很奇怪:你期望 Tfloat,但实际上 BA<long>BA<T>,其中 Tlong.

并且因为 CB 的子代,它是 B 的扩展相同类型,所以 A<long>.

因此,为外部 class.

的泛型类型参数指定的输出 long 而不是 float 的封闭构造类型的结果

因此,无论在创建实例时指定的 T 是什么,对于 f 中的 T 类型,您将始终获得 long

求解

我认为这是一个有点复杂的递归内化,但你不只是需要它吗?

class A<T>
{
  public class B : A<T>
  {
    public void f()
    {
      Console.WriteLine(typeof(T).ToString());
    }

    public class C : B { }

  }
}

这样写:

var c = new A<float>.B.C();
c.f();

将输出:

System.Single

读数

Generics open and closed constructed types

Constructed Types

Generics in .NET

Generics (C# Programming Guide)

C# Generics Level 1

C# Generics Level 2

类型C定义为:

public class C : A<long>.B { }

类型A定义为:

class A<T> {
    public class B : A<long> {
        public void f() {
            Console.WriteLine( typeof(T).ToString());
        }    

    public class C : A<long>.B { }
    } 
}

因此,如果您创建一个新的 C,那么 A 的类型参数是 long

在语句 var c = new A<float>.B.C(); 中,A<float>B 只是嵌套 class C 的“路径”的一部分。 A<float> 是该路径的一部分这一事实不会改变 CA<long>.B.

的事实

float 参数和 B 是一个 A<long> 的事实与确定 c.f()T 的类型无关。