Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.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#_.net - Fatal编程技术网

C#泛型类型是否已装箱?

C#泛型类型是否已装箱?,c#,.net,C#,.net,我执行了以下代码: using System; using System.Collections.Generic; namespace TestReleaseAndDebug { public class GClass<T1, T2> { public T1 Name { get; set; } public T2 Age { get; set; } public void Display()

我执行了以下代码:

using System;
using System.Collections.Generic;

namespace TestReleaseAndDebug
{
    public class GClass<T1, T2>
    {
        public T1 Name { get; set; }      
        public T2 Age { get; set; }

        public void Display()
        {
            Console.WriteLine("Name: " + Name);           
            Console.WriteLine("Age: " + Age);
        }
    }

    class Program
    {        
        static void Main(string[] args)
        {
            GClass<string, int> person = new GClass<string, int>();
            person.Name = "RAM";         
            person.Age = 34;
            string name = "RAM";          
            int age = 34;

            Console.WriteLine("Name: " + name);         
            Console.WriteLine("Age: " + age);           
            person.Display();

            Console.Read();
        }
    }
}
使用系统;
使用System.Collections.Generic;
命名空间TestReleaseAndDebug
{
公共类GClass
{
公共T1名称{get;set;}
公共T2年龄{get;set;}
公共空间显示()
{
Console.WriteLine(“名称:”+名称);
控制台。WriteLine(“年龄:+Age”);
}
}
班级计划
{        
静态void Main(字符串[]参数)
{
GClass person=新的GClass();
person.Name=“RAM”;
人,年龄=34岁;
string name=“RAM”;
年龄=34岁;
Console.WriteLine(“名称:”+名称);
控制台。WriteLine(“年龄:+Age”);
person.Display();
Console.Read();
}
}
}
我在主函数中有两个局部变量,它们是name和age。我正在使用console.writeline方法打印它们。它打印出来没有任何问题。主要方法的IL如下所示:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       90 (0x5a)
  .maxstack  2
  .locals init ([0] class TestReleaseAndDebug.GClass`2<string,int32> person,
           [1] string name,
           [2] int32 age)
  IL_0000:  nop
  IL_0001:  newobj     instance void class TestReleaseAndDebug.GClass`2<string,int32>::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldstr      "RAM"
  IL_000d:  callvirt   instance void class TestReleaseAndDebug.GClass`2<string,int32>::set_Name(!0)
  IL_0012:  nop
  IL_0013:  ldloc.0
  IL_0014:  ldc.i4.s   34
  IL_0016:  callvirt   instance void class TestReleaseAndDebug.GClass`2<string,int32>::set_Age(!1)
  IL_001b:  nop
  IL_001c:  ldstr      "RAM"
  IL_0021:  stloc.1
  IL_0022:  ldc.i4.s   34
  IL_0024:  stloc.2
  IL_0025:  ldstr      "Name: "
  IL_002a:  ldloc.1
  IL_002b:  call       string [mscorlib]System.String::Concat(string,
                                                              string)
  IL_0030:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0035:  nop
  IL_0036:  ldstr      "Age: "
  IL_003b:  ldloc.2
  IL_003c:  box        [mscorlib]System.Int32
  IL_0041:  call       string [mscorlib]System.String::Concat(object,
                                                              object)
  IL_0046:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_004b:  nop
  IL_004c:  ldloc.0
  IL_004d:  callvirt   instance void class TestReleaseAndDebug.GClass`2<string,int32>::Display()
  IL_0052:  nop
  IL_0053:  call       int32 [mscorlib]System.Console::Read()
  IL_0058:  pop
  IL_0059:  ret
} // end of method Program::Main
.method private隐藏静态void Main(字符串[]args)cil托管
{
.入口点
//代码大小90(0x5a)
.maxstack 2
.locals init([0]类TestReleaseAndDebug.GClass`2个人,
[1] 字符串名,
[2] int32(年龄)
IL_0000:没有
IL_0001:newobj实例无效类TestReleaseAndDebug.GClass`2::.ctor()
IL_0006:stloc.0
IL_0007:ldloc.0
IL_0008:ldstr“RAM”
IL_000d:callvirt实例无效类TestReleaseAndDebug.GClass`2::set_Name(!0)
IL_0012:没有
IL_0013:ldloc.0
IL_0014:ldc.i4.s 34
IL_0016:callvirt实例无效类TestReleaseAndDebug.GClass`2::set_Age(!1)
IL_001b:没有
IL_001c:ldstr“RAM”
IL_0021:stloc.1
IL_0022:ldc.i4.s 34
IL_0024:stloc.2
IL_0025:ldstr“名称:”
IL_002a:ldloc.1
IL_002b:call string[mscorlib]System.string::Concat(string,
(字符串)
IL_0030:调用void[mscorlib]System.Console::WriteLine(字符串)
IL_0035:没有
IL_0036:ldstr“年龄:
IL_003b:ldloc.2
IL_003c:box[mscorlib]System.Int32
IL_0041:调用字符串[mscorlib]System.string::Concat(对象,
(对象)
IL_0046:调用void[mscorlib]System.Console::WriteLine(字符串)
IL_004b:没有
IL_004c:ldloc.0
IL_004d:callvirt实例void类TestReleaseAndDebug.GClass`2::Display()
IL_0052:没有
IL_0053:调用int32[mscorlib]System.Console::Read()
IL_0058:流行音乐
IL_0059:ret
}//方法程序结束::Main
我有另一个通用类“GClass”。在泛型类中,我有两个属性和一个方法(Display)。在Display方法中,我显示这两个属性的方式与我在Main方法中显示局部变量的方式相同。通用类显示方法的IL如下所示:

.method public hidebysig instance void  Display() cil managed
{
  // Code size       56 (0x38)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      "Name: "
  IL_0006:  ldarg.0
  IL_0007:  call       instance !0 class TestReleaseAndDebug.GClass`2<!T1,!T2>::get_Name()
  IL_000c:  box        !T1
  IL_0011:  call       string [mscorlib]System.String::Concat(object,
                                                              object)
  IL_0016:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_001b:  nop
  IL_001c:  ldstr      "Age: "
  IL_0021:  ldarg.0
  IL_0022:  call       instance !1 class TestReleaseAndDebug.GClass`2<!T1,!T2>::get_Age()
  IL_0027:  box        !T2
  IL_002c:  call       string [mscorlib]System.String::Concat(object,
                                                              object)
  IL_0031:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0036:  nop
  IL_0037:  ret
} // end of method GClass`2::Display
.method public hidebysing instance void Display()cil managed
{
//代码大小56(0x38)
.maxstack 8
IL_0000:没有
IL_0001:ldstr“名称:”
IL_0006:ldarg.0
IL_0007:调用实例!0类TestReleaseAndDebug.GClass`2::get_Name()
IL_000c:box!T1
IL_0011:调用字符串[mscorlib]System.string::Concat(对象,
(对象)
IL_0016:调用void[mscorlib]System.Console::WriteLine(字符串)
IL_001b:没有
IL_001c:ldstr“年龄:
IL_0021:ldarg.0
IL_0022:调用实例!1类TestReleaseAndDebug.GClass`2::get_Age()
IL_0027:box!T2
IL_002c:调用字符串[mscorlib]System.string::Concat(对象,
(对象)
IL_0031:调用void[mscorlib]System.Console::WriteLine(字符串)
IL_0036:没有
IL_0037:ret
}//方法GClass`2::Display的结尾
我将“string”作为类型参数传递给T1,并使用此类型声明Name属性。当使用Console.Writeline显示Name属性时,它正在装箱名称(IL_000c:box!T1)。你可以在IL找到这个


为什么拳击是一种弦式拳击

编译器必须生成可以跨所有泛型类型工作的IL。编译器无法知道您总是使用
安装
GCClass
。它必须处理
T1
是一种值类型的可能性

但是,我希望引用类型上的
box
是禁止操作的。JIT从
Display
方法的IL为引用和值类型生成不同的机器代码。对于引用类型,我希望删除
指令


如果您确定
T1
永远不会是一个值类型,您可以向其添加
:class
约束,这将删除
指令。

这太了,因为编译器不确定
T1
T2
始终都是引用类型或值类型。因此,对于T1或T2这两种情况,默认情况下都会将它们放入Object中,无论它们是值类型还是引用类型

类型
对象
可以在二元性中起作用
。它可以为值类型取消装箱,并且在引用类型为任何子类时保留对其实例的引用

所以,如果T1是string,它实际上不是装箱,而是保存string实例的引用,因为Object是string类型的基类,实际上是任何.Net类型

如果T2为int,则是简单的装箱拆箱。

查看

在第三部分第4.1节中,关于
说明:

如果typeTok是值类型,则框 指令将val转换为其装箱的值 形式。当typeTok是不可为空的 类型(§1.8.2.4),这由 创建一个