【问题标题】:Boxing Conversion or Identity Conversion?拳击转换还是身份转换?
【发布时间】:2020-03-24 07:07:41
【问题描述】:

我在阅读第三版C# in Depth时偶然发现了这个问题。这本书在 P.74 的表 3.2 中有以下内容。

class Sample<T> where T : IComparable<T> | 有效Sample<int>(装箱转换),无效Sample<FileInfo>

让我们考虑以下内容。

using System;

public class Program
{
    public static void Main()
    {
        Sample<int> s1 = new Sample<int>();                 // ---(1.1)
        Sample<object> s2 = new Sample<object>();           // ---(1.2)
        Sample<OtherSample> s3 = new Sample<OtherSample>(); // ---(1.3)
        s1.Print();
        s2.Print();
    }
}

public class Sample<T> where T : IComparable<T> {
    public void Print() {
        Console.WriteLine(this);
    }
}

public class OtherSample : IComparableExtended<OtherSample> {
    public int CompareTo(OtherSample obj) {
        return 0;
    }
}

public interface IComparableExtended<T> : IComparable<T> {}

显然,1.2 是明显错误的,因为没有从 objectSystem.IComparable&lt;object&gt; 的隐式引用转换。我对 1.1 也确实没有问题,只是书上说它是 Boxing Conversion。现在,int 实际上是Int32 结构的别名,它通过层次结构Object-&gt;ValueType-&gt;Int32 继承。这将接口System.IComparable&lt;T&gt; 实现为IComparable&lt;Int32&gt;,这就是1.1 正确的原因。据我了解,where T : IComparable&lt;T&gt; 的意思是 T 应该是实现 IComparable 的东西。我认为Int32 实现了这个接口,因此满足Sample&lt;T&gt; 的类型约束。从这个意义上说,这真的是本书所暗示的拳击转换吗?或者这是身份转换?

1.3 使这与书中的内容更加混乱和矛盾。当public class Sample&lt;T&gt; where T : IComparable&lt;T&gt;签名改成public class Sample&lt;T&gt; where T : IComparableExtended&lt;T&gt;,连1.1都变成编译时错误。

所以我的问题是,1.1 真的可以被视为拳击转换吗?否则我对拳击和泛型类型转换的整个想法是错误的?

【问题讨论】:

  • 如果不知道您实际询问的是书中的什么文字,就不可能完全理解您的问题。请修正您的问题,以便将您的问题所依据的书中的逐字引用包含在内。
  • 我不明白你对 1.3 有什么问题,虽然我没有读过这本书,所以我不知道它是怎么说的。恕我直言,没有测试,应该没问题,因为OtherSample 实现了一个继承IComparable&lt;T&gt; 的接口,这意味着它也在实现IComparable&lt;T&gt;
  • " 当 public class Sample where T : IComparable 签名更改为 public class Sample where T : IComparableExtended 时,即使 1.1 也成为编译时错误。" ——嗯,你期待什么? int 没有实现 IComparableExtended&lt;int&gt;

标签: c# .net generics boxing


【解决方案1】:

这是一个拳击转换。

快速浏览文档将带您进入Boxing and Unboxing (C# Programming Guide) 页面,该页面以以下文本开头:

装箱是将值类型转换为类型对象或此值类型实现的任何接口类型的过程。

(强调我的)

由于Sample&lt;T&gt; 是在接口上使用通用约束定义的,所以它会在使用它初始化时将实现此接口的任何结构装箱。

【讨论】:

  • 您摘录之后的句子(当公共语言运行时 (CLR) 将值类型装箱时,它会将值包装在 System.Object 实例中并将其存储在托管堆中 i>) 我认为误导了我。感谢您的澄清。现在加起来了..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-25
  • 1970-01-01
  • 1970-01-01
  • 2016-09-11
  • 1970-01-01
相关资源
最近更新 更多