Тип X нельзя использовать в качестве параметра типа T в универсальном типе Y - PullRequest
0 голосов
/ 20 января 2019

Я не вижу, что не так с приведенным ниже кодом или как я могу это исправить.(Возможно, я неправильно понимаю универсальные типы.)

class X<I>
   where I : ISomeInterface
{ }

class Y<T>
   where T : X<ISomeInterface>
{ }

class Z<I>
   where I : ISomeInterface
{
   Y<X<I>> AData { get; } // What compiler does not like
   Y<X<ISomeInterface>> BData { get; } // What compiler likes
}

Компилятор жалуется, что не может использовать X<I> в качестве параметра типа T в универсальном типе Y<T>.

1 Ответ

0 голосов
/ 20 января 2019

Вот рабочее решение

interface ISomeInterface {}

class X<I>
   where I : ISomeInterface
{ }

class Y<T, I>
   where T : X<I>
   where I : ISomeInterface
{ }

class Z<I>
   where I : ISomeInterface
{
   Y<X<I>, I> MyOtherData { get; set; }
   Y<X<ISomeInterface>, ISomeInterface> MyData { get; set; }
}

Обратите внимание на дополнительный универсальный параметр I и ограничения, которые я добавил к определению типа Y.

Ваше первоначальное определение Y слишком ограничительно.C # делает различие между ISomeInterface и любым типом, реализующим ISomeInterface.

Почему это так?

.NET-компилятор имеет особый способ обработки универсальных типов.Для каждого универсального типа компилятор создаст отдельный тип на основе аргументов универсального типа, который вместо этого используется во время выполнения.Например, List<int> и List<string> будут совершенно разными типами, причем все будут демонстрировать поведение, определенное универсальным типом List<_>, но с фактическим типом int или string, встроенным в конкретный тип, сгенерированный компилятором.

Когда вы определяете class Y<T> where T : X<ISomeInterface>, вы «запечатываете» общий параметр X, равный ISomeInterface.Компилятор примет любой тип, наследующий X<ISomeInterface>, но не X<SomethingElse>, даже если SomethingElse сам является реализацией ISomeInterface.Это связано с тем, что фрагмент where T : X<ISomeInterface> вызывает "запекание" ISomeInterface в определении типа Y<T>.Такое поведение является ожидаемым и является побочным эффектом того, как обобщенные элементы компилируются в реальный код.По той же причине нельзя делать следующее:

List<object> x = new List<string>();

, хотя тип string наследуется от object.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...