Я наткнулся на эту проблему, когда читал 3-е издание C# в глубине . Книга содержит следующее в Таблице 3.2 на стр.74.
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 явно ошибочен, поскольку не существует неявного преобразования ссылок из object
в System.IComparable<object>
. У меня действительно нет проблем с 1.1, кроме того, что в книге написано, что это Boxing Conversion . Теперь int
на самом деле является псевдонимом для Int32
struct, которая наследуется через иерархию Object->ValueType->Int32
. Это реализует интерфейс System.IComparable<T>
как IComparable<Int32>
, поэтому версия 1.1 верна. Как я понял, where T : IComparable<T>
означает, что T должно быть чем-то, что реализует IComparable . Я полагал, что Int32
реализует этот интерфейс и, следовательно, удовлетворяет ограничению типа для Sample<T>
. В этом смысле действительно ли это Бокс Конверсия, как предполагает книга? Или это преобразование идентичности?
1.3 делает это еще более запутанным и противоречивым тому, что в книге. Когда public class Sample<T> where T : IComparable<T>
сигнатура изменяется на public class Sample<T> where T : IComparableExtended<T>
, даже 1.1 становится ошибкой времени компиляции.
Так что мой вопрос: можно ли рассматривать 1.1 как конвертирование в бокс? Или же вся моя идея о боксе и преобразованиях типа generi c неверна?